#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Gitdwn 靶机 — Gitea Webhook Bearer Token 解密脚本 ===================================================== 解密 Gitea webhook 表中 header_authorization_encrypted 字段。 Gitea 使用 AES-256-CFB 模式加密敏感字段: - Key: SHA256(SECRET_KEY) → 32 bytes - IV: 加密数据的前 16 bytes - Ciphertext: 加密数据的第 17 字节起 用法: # 解密单个加密值 python3 03_gitea_webhook_decrypt.py # 交互式输入 python3 03_gitea_webhook_decrypt.py --interactive 前提: 需要先通过 XXE 或 SSH 获取: 1. SECRET_KEY (来自 /etc/gitea/app.ini) 2. header_authorization_encrypted (来自 gitea.db webhook 表) 依赖: pip install pycryptodome """ import sys import hashlib import base64 from Crypto.Cipher import AES # ============================================================ # 从靶机获取的实际值 # ============================================================ SECRET_KEY = "mazesec_ctf_key_123" ENCRYPTED_HEX = "e4a28a7a1dd990616c1314e61f5958f83717fbea95af00eadaa0e4bd65d8e771338ca3a175f57d33fd05ea81" def decrypt_gitea_webhook(secret_key, encrypted_hex): """ 解密 Gitea 加密的 webhook header_authorization_encrypted 字段。 Gitea 加密格式 (modules/secret/secret.go): - Key = SHA256(SECRET_KEY) → 取前 32 bytes - IV = 加密数据前 16 bytes - 加密算法 = AES-256-CFB (segment_size=128 bit) - 密文 = 加密数据从第 17 字节开始 Args: secret_key: Gitea SECRET_KEY (app.ini → [security]) encrypted_hex: webhook 表中 header_authorization_encrypted Returns: 解密后的明文字符串 """ # Step 1: 派生 AES Key key = hashlib.sha256(secret_key.encode()).digest() print(f"[*] SECRET_KEY: {secret_key}") print(f"[*] AES Key: {key.hex()}") print(f"[*] Key length: {len(key)} bytes (AES-256)") # Step 2: 解析加密数据 encrypted = bytes.fromhex(encrypted_hex) iv = encrypted[:16] # 前 16 bytes = IV ciphertext = encrypted[16:] # 剩余 = 密文 print(f"[*] Encrypted: {len(encrypted)} bytes") print(f"[*] IV: {iv.hex()}") print(f"[*] Ciphertext: {ciphertext.hex()} ({len(ciphertext)} bytes)") # Step 3: AES-256-CFB 解密 cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128) plaintext = cipher.decrypt(ciphertext) print(f"[*] Plaintext: {plaintext}") return plaintext.decode("utf-8", errors="replace") def main(): if "--interactive" in sys.argv or "-i" in sys.argv: secret_key = input("SECRET_KEY: ").strip() or SECRET_KEY encrypted_hex = input("header_authorization_encrypted: ").strip() or ENCRYPTED_HEX else: secret_key = SECRET_KEY encrypted_hex = ENCRYPTED_HEX print("[*] 使用预设值,可通过 --interactive 交互式输入\n") result = decrypt_gitea_webhook(secret_key, encrypted_hex) print(f"\n{'='*60}") print(f"解密结果: {result}") print(f"{'='*60}") # 尝试二次 Base64 解码 (Gitea webhook Bearer token 通常 base64 编码) try: # 如果结果是 "Bearer " 格式 if result.startswith("Bearer "): inner_b64 = result.split(" ", 1)[1] inner_decoded = base64.b64decode(inner_b64).decode("utf-8", errors="replace") print(f"\n[*] 二次解码 (Bearer Token → Base64):") print(f" {result}") print(f" ↓ 去掉 'Bearer ' 前缀后 Base64 解码") print(f" {inner_decoded}") except Exception: pass # 也尝试对完整结果做 Base64 解码 try: decoded = base64.b64decode(result).decode("utf-8", errors="replace") if decoded != result: print(f"\n[*] 完整结果 Base64 解码: {decoded}") except Exception: pass if __name__ == "__main__": main()