如何测试加密站点
字数 1344 2025-08-24 10:10:13

加密站点渗透测试技术详解:BurpSuite与mitmproxy实战指南

0x1 前言

在渗透测试过程中,经常会遇到返回数据部分或全部加密的情况。本文详细介绍了两种处理加密站点的实用方法:BurpSuite插件和mitmproxy模块。这两种方法都需要使用Python编写脚本,适用于不同场景下的加密数据处理。

0x2 Burpy插件使用详解

2.1 应用场景

在对小程序接口测试时,发现返回的用户个人信息中关键字段(姓名、电话、身份证号等)被加密,需要通过解密数据来验证漏洞危害性。

2.2 安装与配置

  1. 下载Burpy插件:https://github.com/mr-m0nst3r/Burpy
  2. 配置BurpSuite:
    • 设置Python路径
    • 设置脚本路径
    • 启动插件

2.3 脚本编写要点

主要需要实现encryptdecrypt两个函数,对于局部加密的数据需要特别处理:

import json
from Crypto.Cipher import AES
import base64

class Burpy:
    def __init__(self):
        pass
    
    def encrypt(self, header, body):
        header["Cookie"] = "admin=1"
        return header, body
    
    def decrypt(self, header, body):
        new_data = json.loads(body)
        for i in new_data['data']['records']:
            i["visitorName"] = str(aesd(i['visitorName']))
            i["visitorTelephone"] = str(aesd(i['visitorTelephone']))
            i["visitorIdentityNumber"] = str(aesd(i['visitorIdentityNumber']))
            i["personName"] = str(aesd(i['personName']))
            i["personTelephone"] = str(aesd(i['personTelephone']))
        data = json.dumps(new_data, indent=4, ensure_ascii=False)
        return header, data

def aesd(s):
    BS = AES.block_size
    pad = lambda s: s + (BS - len(s) % BS) * bytes([BS - len(s) % BS])
    unpad = lambda s: s[0:-s[-1]]
    key = b"xxxxxxxxxxxxxxxx"
    ciphertext_b64 = s
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = base64.b64decode(ciphertext_b64)
    plaintext_padded = cipher.decrypt(ciphertext)
    plaintext = unpad(plaintext_padded)
    return plaintext.decode()

2.4 使用方法

  1. 右键点击数据包,选择"Decrypt"查看解密数据
  2. 或开启"Auto Enc/Dec"功能自动处理

0x3 mitmproxy代理方案

3.1 基本响应包解密

以有道翻译为例,处理AES加密的响应数据:

from Crypto.Cipher import AES
from mitmproxy import flowfilter
from mitmproxy.http import HTTPFlow
import base64

class Mimit():
    def response(self, flow):
        resp = flow.response.get_text()
        rep = AES_Decrypt(resp)
        flow.response.set_text(rep)

def AES_Decrypt(data):
    key = b'\x08\x14\x9d\xa7\x3c\x59\xce\x62\x55\x5b\x01\xe9\x2f\x34\xe8\x38'
    iv = b'\xd2\xbb\x1b\xfd\xe8\x3b\x38\xc3\x44\x36\x63\x57\xb7\x9c\xae\x1c'
    aes = AES.new(key, AES.MODE_CBC, iv)
    rep = aes.decrypt(base64.urlsafe_b64decode(data)).decode('utf-8')
    return rep

addons = [Mimit(),]

启动命令:

mitmdump -p 9090 -s ./test.py --ssl-insecure

3.2 请求体和响应体同时加密处理

对于双向加密的站点,需要设置两层代理:

  1. 下游代理:解密浏览器发送的数据,加密服务器返回的数据
  2. 上游代理:加密发送给服务器的数据,解密服务器返回的数据

下游代理代码

from mitmproxy import flowfilter, ctx
from mitmproxy.http import HTTPFlow
from Crypto.Util.Padding import pad
import json
from Crypto.Cipher import AES
import base64
from urllib.parse import unquote

class Mimit():
    def request(self, flow):
        if flow.request.host == "127.0.0.1":
            req = flow.request.get_text()
            ctx.log.info("请求数据 => " + unquote(req))
            if IsJson(req):
                flow.request.set_text(req)
            else:
                data = AesDecrypt(req)
                flow.request.set_text(data)
    
    def response(self, flow):
        rep = flow.response.get_text()
        ctx.log.info("响应数据 => " + flow.response.get_text())
        if IsJson(rep):
            rep = Encrypt_data(rep, "aa834085ebd67a24")
            flow.response.set_text(rep)
        else:
            flow.response.set_text(rep)

def AesDecrypt(s):
    BS = AES.block_size
    pad = lambda s: s + (BS - len(s) % BS) * bytes([BS - len(s) % BS])
    unpad = lambda s: s[0:-s[-1]]
    key = b"aa834085ebd67a24"
    ciphertext_b64 = s
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = base64.b64decode(ciphertext_b64)
    plaintext_padded = cipher.decrypt(ciphertext)
    plaintext = unpad(plaintext_padded)
    return plaintext.decode()

def Encrypt_data(data, key):
    aes = AES.new(key.encode("utf-8"), AES.MODE_ECB)
    pad_pkcs7 = pad(data.encode('utf-8'), AES.block_size, style='pkcs7')
    res = aes.encrypt(pad_pkcs7)
    msg = str(base64.b64encode(res), encoding="utf-8")
    return msg

def IsJson(data):
    try:
        data = json.loads(data)
        return True
    except:
        return False

addons = [Mimit(),]

上游代理代码

from mitmproxy import flowfilter, ctx
from mitmproxy.http import HTTPFlow
from Crypto.Util.Padding import pad
import json
from Crypto.Cipher import AES
import base64
from urllib.parse import unquote

class Mimit():
    def request(self, flow):
        if flow.request.host == "127.0.0.1":
            req = flow.request.get_text()
            ctx.log.info("请求数据 => " + unquote(req))
            if IsJson(req):
                data = Encrypt_data(req, "aa834085ebd67a24")
                flow.request.set_text(data)
            else:
                flow.request.set_text(req)
    
    def response(self, flow):
        resp = flow.response.get_text()
        ctx.log.info("返回数据 => " + resp)
        if IsJson(resp):
            flow.response.set_text(resp)
        else:
            resp = AesDecrypt(resp)
            flow.response.set_text(resp)

def AesDecrypt(s):
    BS = AES.block_size
    pad = lambda s: s + (BS - len(s) % BS) * bytes([BS - len(s) % BS])
    unpad = lambda s: s[0:-s[-1]]
    key = b"aa834085ebd67a24"
    ciphertext_b64 = s
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = base64.b64decode(ciphertext_b64)
    plaintext_padded = cipher.decrypt(ciphertext)
    plaintext = unpad(plaintext_padded)
    return plaintext.decode()

def Encrypt_data(data, key):
    aes = AES.new(key.encode("utf-8"), AES.MODE_ECB)
    pad_pkcs7 = pad(data.encode('utf-8'), AES.block_size, style='pkcs7')
    res = aes.encrypt(pad_pkcs7)
    msg = str(base64.b64encode(res), encoding="utf-8")
    return msg

def IsJson(data):
    try:
        data = json.loads(data)
        return True
    except:
        return False

addons = [Mimit(),]

启动命令

下游代理:

mitmdump -p 7070 -s ./downstream.py --mode upstream:https://127.0.0.1:8080 --ssl-insecure

上游代理:

mitmdump -p 9090 -s ./upstream.py --ssl-insecure

0x4 与其他工具结合

4.1 与sqlmap结合

使用单层上游代理即可:

  1. 将解密好的payload给sqlmap
  2. sqlmap发送给上游代理
  3. 上游代理加密后发送给服务器
  4. 服务器返回数据给上游代理
  5. 上游代理解密后返回给sqlmap

启动命令:

mitmdump -p 9090 -s ./sqlmap_proxy.py --ssl-insecure

sqlmap命令:

sqlmap -r sql.txt -proxy http://192.168.1.5:9090

4.2 与xray结合

需要设置两层代理:

  1. 第一层代理:解密浏览器发送的数据
  2. 第二层代理:加密发送给xray的数据和解密xray返回的数据

第一层代理代码

from mitmproxy import flowfilter, ctx
from mitmproxy.http import HTTPFlow
from Crypto.Util.Padding import pad
import json
from Crypto.Cipher import AES
import base64
from urllib.parse import unquote

class Mimit():
    def request(self, flow):
        if flow.request.host == "127.0.0.1":
            req = flow.request.get_text()
            ctx.log.info("请求数据 => " + unquote(req))
            if IsJson(req):
                flow.request.set_text(req)
            else:
                data = AesDecrypt(req)
                flow.request.set_text(data)
    
    def response(self, flow):
        pass

def AesDecrypt(s):
    BS = AES.block_size
    pad = lambda s: s + (BS - len(s) % BS) * bytes([BS - len(s) % BS])
    unpad = lambda s: s[0:-s[-1]]
    key = b"aa834085ebd67a24"
    ciphertext_b64 = s
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = base64.b64decode(ciphertext_b64)
    plaintext_padded = cipher.decrypt(ciphertext)
    plaintext = unpad(plaintext_padded)
    return plaintext.decode()

def IsJson(data):
    try:
        data = json.loads(data)
        return True
    except:
        return False

addons = [Mimit(),]

第二层代理代码

与之前的上游代理代码相同

配置与启动

  1. 启动下游代理:

    mitmdump -p 7070 -s ./xray_downstream.py --mode upstream:https://127.0.0.1:8090 --ssl-insecure
    
  2. 启动上游代理:

    mitmdump -p 9090 -s ./xray_upstream.py --ssl-insecure
    
  3. 配置xray代理,修改config文件

  4. 启动xray:

    xray.exe -ws --listen 127.0.0.1:8090
    
  5. 配置浏览器代理端口为7070

0x5 测试环境搭建

前端代码示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户查询</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
</head>
<body>
    <script>
    function decryptAES(data, key) {
        var key = CryptoJS.enc.Utf8.parse(key);
        var decrypt = CryptoJS.AES.decrypt(data, key, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        return CryptoJS.enc.Utf8.stringify(decrypt).toString();
    };
    
    function sendNumber() {
        var num = $('#numberInput').val();
        var data = { number: num };
        var datas = JSON.stringify(data);
        const aesKey = CryptoJS.enc.Utf8.parse("aa834085ebd67a24");
        var encrypted = CryptoJS.AES.encrypt(datas, aesKey, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        }).toString();;
        console.log(encrypted);
        
        $.ajax({
            url: 'query.php',
            type: 'POST',
            data: encrypted,
            success: function(response) {
                var result = decryptAES(response, "aa834085ebd67a24");
                document.getElementById("result").innerHTML = result;
            },
            error: function(xhr, status, error) {
                console.log(error);
            }
        });
    }
    </script>
    <input type="text" id="numberInput">
    <button onclick="sendNumber()">发送</button>
    <div id="result">结果:</div>
</body>
</html>

后端PHP代码示例

<?php
function aes_encrypt($data, $key) {
    $cipher = "aes-128-ecb";
    $options = OPENSSL_RAW_DATA;
    $key = substr($key, 0, 16);
    $result = openssl_encrypt($data, $cipher, $key, $options);
    return base64_encode($result);
}

function aes_decrypt($data, $key) {
    $cipher = "aes-128-ecb";
    $options = OPENSSL_RAW_DATA;
    $key = substr($key, 0, 16);
    $result = openssl_decrypt(base64_decode($data), $cipher, $key, $options);
    return $result;
}

$data = file_get_contents('php://input');
$number = aes_decrypt($data, "aa834085ebd67a24");
$num = json_decode($number, true)['number'];

$con = mysqli_connect("localhost", "root", "123456", "db_name");
if (mysqli_connect_errno()) {
    echo "连接失败: " . mysqli_connect_error();
}

$result = mysqli_query($con, "SELECT * FROM v9_admin WHERE userid={$num}");
while($row = mysqli_fetch_array($result)) {
    $str = array(
        'username' => $row['username'],
        'password' => $row['password'],
        'lastloginip' => $row['lastloginip'],
        'email' => $row['email']
    );
}

$a = json_encode($str);
$results = aes_encrypt($a, "aa834085ebd67a24");
echo $results;
?>

0x6 总结与注意事项

  1. 加密类型判断

    • 全数据包加密处理较简单
    • 局部加密数据需要精确识别加密字段
    • JSON格式数据可通过json.loads()判断是否为明文
  2. 算法逆向要点

    • 必须找到加密算法和密钥信息
    • 需要调试前端JavaScript代码或逆向移动应用
    • 常见加密方式:AES ECB/CBC模式、RSA等
  3. 工具选择建议

    • 简单解密需求:Burpy插件
    • 复杂双向加密:mitmproxy多层代理
    • 自动化扫描:结合xray或sqlmap
  4. 常见问题

    • 部分接口加密/部分不加密的情况需要特殊处理
    • 防止二次加密导致数据异常
    • 注意加密模式(ECB/CBC等)和填充方式(PKCS7等)

0x7 参考资源

  1. Burpy插件使用指南
  2. mitmproxy高级用法

通过本文介绍的技术方案,可以有效解决渗透测试过程中遇到的各种数据加密问题,提高测试效率和漏洞发现能力。

加密站点渗透测试技术详解:BurpSuite与mitmproxy实战指南 0x1 前言 在渗透测试过程中,经常会遇到返回数据部分或全部加密的情况。本文详细介绍了两种处理加密站点的实用方法:BurpSuite插件和mitmproxy模块。这两种方法都需要使用Python编写脚本,适用于不同场景下的加密数据处理。 0x2 Burpy插件使用详解 2.1 应用场景 在对小程序接口测试时,发现返回的用户个人信息中关键字段(姓名、电话、身份证号等)被加密,需要通过解密数据来验证漏洞危害性。 2.2 安装与配置 下载Burpy插件:https://github.com/mr-m0nst3r/Burpy 配置BurpSuite: 设置Python路径 设置脚本路径 启动插件 2.3 脚本编写要点 主要需要实现 encrypt 和 decrypt 两个函数,对于局部加密的数据需要特别处理: 2.4 使用方法 右键点击数据包,选择"Decrypt"查看解密数据 或开启"Auto Enc/Dec"功能自动处理 0x3 mitmproxy代理方案 3.1 基本响应包解密 以有道翻译为例,处理AES加密的响应数据: 启动命令: 3.2 请求体和响应体同时加密处理 对于双向加密的站点,需要设置两层代理: 下游代理 :解密浏览器发送的数据,加密服务器返回的数据 上游代理 :加密发送给服务器的数据,解密服务器返回的数据 下游代理代码 上游代理代码 启动命令 下游代理: 上游代理: 0x4 与其他工具结合 4.1 与sqlmap结合 使用单层上游代理即可: 将解密好的payload给sqlmap sqlmap发送给上游代理 上游代理加密后发送给服务器 服务器返回数据给上游代理 上游代理解密后返回给sqlmap 启动命令: sqlmap命令: 4.2 与xray结合 需要设置两层代理: 第一层代理 :解密浏览器发送的数据 第二层代理 :加密发送给xray的数据和解密xray返回的数据 第一层代理代码 第二层代理代码 与之前的上游代理代码相同 配置与启动 启动下游代理: 启动上游代理: 配置xray代理,修改config文件 启动xray: 配置浏览器代理端口为7070 0x5 测试环境搭建 前端代码示例 后端PHP代码示例 0x6 总结与注意事项 加密类型判断 : 全数据包加密处理较简单 局部加密数据需要精确识别加密字段 JSON格式数据可通过 json.loads() 判断是否为明文 算法逆向要点 : 必须找到加密算法和密钥信息 需要调试前端JavaScript代码或逆向移动应用 常见加密方式:AES ECB/CBC模式、RSA等 工具选择建议 : 简单解密需求:Burpy插件 复杂双向加密:mitmproxy多层代理 自动化扫描:结合xray或sqlmap 常见问题 : 部分接口加密/部分不加密的情况需要特殊处理 防止二次加密导致数据异常 注意加密模式(ECB/CBC等)和填充方式(PKCS7等) 0x7 参考资源 Burpy插件使用指南 mitmproxy高级用法 通过本文介绍的技术方案,可以有效解决渗透测试过程中遇到的各种数据加密问题,提高测试效率和漏洞发现能力。