前言:
本方案适用于请求包与响应包为全加密以及有签名校验的情景,实现Mimtproxy+Burp配合下的无痛对AES加解密的网站进行渗透测试,后续可联动被动扫描xray等工具,遇到其他情况可根据实际情况更改脚本,思路大概一致。
靶场搭建:
https://github.com/0ctDay/encrypt-decrypt-vuls/

先分析JS中的加解密方法:

分析得加解密为AES,得到密钥与IV均为1234567891234567
编写Mimtproxy解密脚本:
from mitmproxy import http from Crypto.Cipher import AES import base64
KEY = b'1234567891234567' IV = b'1234567891234567'
def decrypt_aes_cbc_pkcs7(encrypted_data): """ 解密 AES-CBC-PKCS7 加密的数据 """ cipher = AES.new(KEY, AES.MODE_CBC, IV) decrypted_data = cipher.decrypt(encrypted_data) padding_len = decrypted_data[-1] decrypted_data = decrypted_data[:-padding_len] return decrypted_data
def request(flow: http.HTTPFlow) -> None: if flow.request.host == "192.168.200.22": encrypted_body = flow.request.content try: encrypted_body_bytes = base64.b64decode(encrypted_body) decrypted_body = decrypt_aes_cbc_pkcs7(encrypted_body_bytes) flow.request.content = decrypted_body print("解密成功!") except Exception as e: print(f"解密失败:{e}") flow.request.content = encrypted_body
|
此处只解密了请求包,无需解密响应包,因为此时请求包为明文,发过去服务器也无法识别
其中脚本可根据实际换成其他限定的Host,符合条件的进行解密,否则放行,无法解密也放行
数据包原始内容:

启动脚本对请求包进行解密处理:

浏览器代理8010,也就是代理到mitmproxy监听的端口,然后mitmproxy的上游给到burp,也就是把数据包传到burp
mitmdump -p 8010 -s decrypt.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure

查看到Burp的效果:

此处请求已变成明文,但此时发送到服务器是无法识别的,所以要再将其加密回去

而请求包是带有签名校验的,需要先还原签名校验算法


requestID生成逻辑已有,可以模拟还原,整体签名流程是对body的明文内容+requestID+时间戳进行MD5
编写Mimtproxy加密+签名校验脚本:
from mitmproxy import http from Crypto.Cipher import AES import base64 import json import hashlib import time import random import string
KEY = b'1234567891234567' IV = b'1234567891234567'
def encrypt_aes_cbc_pkcs7(data): """ 使用 AES-CBC-PKCS7 模式加密数据 """ if isinstance(data, str): data = data.encode('utf-8') block_size = AES.block_size padding_len = block_size - (len(data) % block_size) padding = bytes([padding_len] * padding_len) padded_data = data + padding cipher = AES.new(KEY, AES.MODE_CBC, IV) encrypted_data = cipher.encrypt(padded_data) return base64.b64encode(encrypted_data).decode('utf-8')
def decrypt_aes_cbc_pkcs7(encrypted_data): """ 解密 AES-CBC-PKCS7 加密的数据 """ encrypted_data_bytes = base64.b64decode(encrypted_data) cipher = AES.new(KEY, AES.MODE_CBC, IV) decrypted_data = cipher.decrypt(encrypted_data_bytes) padding_len = decrypted_data[-1] decrypted_data = decrypted_data[:-padding_len] return decrypted_data
def generate_uuid(): """ 生成符合要求的 UUID 字符串 """ hex_digits = "0123456789abcdef" s = [random.choice(hex_digits) for _ in range(32)] s[14] = '4' s[19] = hex_digits[(int(s[19], 16) & 0x3) | 0x8] s[8] = s[13] = s[18] = s[23] = '' return ''.join(s)
def generate_sign(data, request_id, timestamp): """ 生成签名 """ if isinstance(data, bytes): data = data.decode('utf-8') sign_str = data + request_id + str(timestamp) md5 = hashlib.md5() md5.update(sign_str.encode('utf-8')) return md5.hexdigest()
def sort_ascii(data): """ 按 ASCII 码排序数据(模拟前端的 sortASCII 函数) """ if not isinstance(data, dict): return data sorted_data = {} for key in sorted(data.keys()): sorted_data[key] = sort_ascii(data[key]) return sorted_data
def request(flow: http.HTTPFlow) -> None: if flow.request.host == "192.168.200.22": try: plaintext_body = flow.request.content data = json.loads(plaintext_body) sorted_data = sort_ascii(data) timestamp = int(time.time() * 1000) request_id = generate_uuid() sign = generate_sign(json.dumps(sorted_data, separators=(',', ':')), request_id, timestamp) encrypted_body = encrypt_aes_cbc_pkcs7(json.dumps(data, separators=(',', ':'))) final_encrypted_body = encrypted_body flow.request.headers["Content-Type"] = "application/json;charset=utf-8" flow.request.headers["Content-Length"] = str(len(final_encrypted_body)) flow.request.headers["timestamp"] = str(timestamp) flow.request.headers["requestId"] = request_id flow.request.headers["sign"] = sign flow.request.content = final_encrypted_body.encode('utf-8') print("加密成功!") except Exception as e: print(f"加密失败:{e}")
def response(flow: http.HTTPFlow) -> None: """ 解密响应体 """ if flow.request.host == "192.168.200.22": try: encrypted_body = flow.response.content.decode('utf-8') decrypted_body = decrypt_aes_cbc_pkcs7(encrypted_body) decrypted_body_str = decrypted_body.decode('utf-8') flow.response.content = decrypted_body_str.encode('utf-8') print("解密成功!") except Exception as e: print(f"解密失败:{e}")
|
再启动另一个Mitmproxy,监听端口8020
mitmdump -p 8020 -s encrypt.py --ssl-insecure

此时Burp设置上游代理到Mitmproxy监听的端口

下面查看效果:
Proxy:

Repeater:

至此,可以无痛进行一系列爆破或其他测试


同一接口下,无mitmproxy与启动mitmproxy对比:


如果联动xray,需要基于以上配置改换一下:
Burp设置上游为xray监听的7777

Xray的config.yaml设置代理127.0.0.1:8020,也就是第二个mitmproxy

设置扫描白名单为搭建的靶场:

Xray启动监听7777:
xray_windows_amd64.exe webscan --listen 127.0.0.1:7777 --html-output test.html


联动成功,成功开始漏洞,以及检测出敏感数据