一次前端RSA加密之使用Mitmdump自动化加解密渗透测试
字数 1225 2025-08-11 08:36:04

前端RSA加密渗透测试:使用Mitmdump实现自动化加解密

1. 背景与问题描述

在渗透测试过程中,经常会遇到前端加密的情况,这给常规的测试带来了挑战。本文档将详细介绍如何通过逆向分析前端加密逻辑,并使用Mitmdump工具实现自动化加解密,从而顺利进行渗透测试。

1.1 常见问题场景

  • 请求体和响应体均被加密,密文格式为d1,d2,d3
  • 前端使用复杂的加密算法组合(如AES+RSA)
  • Webpack打包的Vue项目增加了逆向难度

2. JS逆向分析

2.1 加密流程分析

通过浏览器开发者工具分析,发现加密流程如下:

  1. d1生成:使用AES-CBC模式加密原始报文
    • Key: 随机值n
    • IV: 随机值o
  2. d2生成:使用服务端公钥加密随机值n
  3. d3生成:使用服务端公钥加密随机值o

2.2 解密流程分析

响应体解密流程:

  1. 使用客户端私钥解密d2得到n
  2. 使用客户端私钥解密d3得到o
  3. 使用n和o解密d1得到原始报文

2.3 关键点定位

  1. 在控制台搜索"d1:"定位加密函数
  2. 下断点分析变量值:
    • e为AES key
    • i为AES iv
    • t为加密前的请求体
  3. 公钥获取:通过断点查看rsa值

3. Webpack代码提取

3.1 Webpack通用提取方法

  1. 搜索"call"定位入口函数
  2. 构建模块加载器框架:
var test_module;
(function(e) {
    var u = {};
    function f(c) {
        if (u[c]) return u[c].exports;
        var n = u[c] = {
            i: c,
            l: !1,
            exports: {}
        };
        console.log(c);
        return e[c].call(n.exports, n, n.exports, f),
        n.l = !0,
        n.exports
    }
    test_module = f;
})({
    // 抠取的代码放在这里
});

3.2 加密函数提取

提取AES加密相关代码:

"4b2a": function(t, e, i) {
    "use strict";
    i.d(e, "a", (function() { return n } )),
    i.d(e, "c", (function() { return o } )),
    i.d(e, "b", (function() { return a } )),
    i.d(e, "d", (function() { return u } )),
    i.d(e, "f", (function() { return c } )),
    i.d(e, "e", (function() { return f } ));
    i("d3b7");
    var r = i("7c74").sm2;
    function n() {
        var t = r.generateKeyPairHex();
        return new Promise((function(e) { t && e(t) }));
    }
    function o(t, e) {
        var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1,
            n = "04" + r.doEncrypt(t, e, i);
        return n
    }
    function a(t, e) {
        var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1,
            n = r.doDecrypt(t.substring(2), e, i);
        return n
    }
    var s = i("7c74").sm3;
    function u(t) {
        var e = s(t);
        return e
    }
    var h = i("7c74").sm4;
    function c(t, e, i) {
        var r = h.encrypt(t, e, { mode: "cbc", iv: i });
        return r
    }
    function f(t, e, i) {
        var r = h.decrypt(t, e, { mode: "cbc", iv: i });
        return r
    }
}

3.3 代码补全策略

  1. 使用console.log提示缺失函数
  2. 按需补全依赖函数
  3. 对于无返回值的调用(i("d3b7"))可注释掉

4. Mitmdump自动化加解密

4.1 适用场景

  1. Web网页端防篡改及加解密
  2. App端防篡改及加解密
  3. 小程序端防篡改及加解密

4.2 代理架构

  1. 二级代理(仅响应体解密):

    • Burp上游代理指向Mitmdump
  2. 三级代理(请求体和响应体加解密):

    • Burp上游代理指向Mitmdump1
    • Mitmdump2上游代理指向Burp

4.3 Python脚本模板

import execjs
from mitmproxy import flowfilter
from mitmproxy.http import HTTPFlow
import subprocess
import json
from functools import partial

# 解决js代码中中文编码错误
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')

with open("test.js", "r", encoding="utf-8") as f:
    js_code = f.read()
    f.close()

ctx = execjs.compile(js_code)

# 请先修改公钥
publickey = ""
# 请先修改私钥
privatekey = ""

def enc(data):
    [d1, d2, d3] = ctx.call("req_enc", data, publickey)
    return [d1, d2, d3]

def dec(d1, d2, d3):
    result = ctx.call("res_dec", d1, d2, d3, privatekey)
    return result

class FilterFlow:
    def request(self, flow):
        if flow.request.url.startswith("https://x.x.x.x/"):
            req = flow.request.get_text()
            if '"d1":' in req:
                return
            print("加密数据前:".format(req))
            data = enc(req)
            d1 = data[0]
            d2 = data[1]
            d3 = data[2]
            json_data = {"d1": d1, "d2": d2, "d3": d3}
            result = json.dumps(json_data)
            print("加密数据后:".format(result))
            flow.request.set_text(result)

    def response(self, flow: HTTPFlow):
        if flow.request.url.startswith("https://x.x.x.x/"):
            resp = flow.response.get_text()
            data = json.loads(resp)
            d1 = data["d1"]
            d2 = data["d2"]
            d3 = data["d3"]
            result = dec(d1, d2, d3)
            flow.response.set_text(result)

addons = [
    FilterFlow(),
]

4.4 代理设置命令

  1. 响应体解密(二级代理):
mitmdump -p 9090 -s ./test.py --ssl-insecure
  1. 请求体和响应体加解密(三级代理):
# 第一个终端(Burp上游代理)
mitmdump -p 9090 -s ./test.py --ssl-insecure

# 第二个终端(Burp下游代理)
mitmdump -p 7070 -s ./test.py --mode upstream:https://127.0.0.1:8080 --ssl-insecure

4.5 Burp设置

  1. User Options => Upstream Proxy Servers => Add
    • 目标主机:目标网站域名
    • 代理主机:127.0.0.1
    • 代理端口:9090

5. 与其他工具集成

使用sqlmap等工具时,通过代理将流量导向Burp:

python sqlmap.py -u "https://x.x.x.x/?id=1" --batch --proxy=http://127.0.0.1:8080

6. 关键注意事项

  1. 确保获得合法授权后再进行测试
  2. 保存完整的JS代码以便后续分析
  3. 注意加密算法中可能的自定义修改(如非常规IV长度)
  4. 测试过程中记录加解密前后的数据对比
  5. 对于复杂的加密逻辑,可能需要分步验证各环节

7. 总结

通过本文介绍的方法,可以有效地处理前端加密场景下的渗透测试问题。关键在于:

  1. 准确分析加密逻辑
  2. 完整提取加密函数
  3. 合理配置代理链
  4. 实现自动化加解密流程

这种方法不仅适用于Web应用,也可应用于App和小程序的加密通信分析。

前端RSA加密渗透测试:使用Mitmdump实现自动化加解密 1. 背景与问题描述 在渗透测试过程中,经常会遇到前端加密的情况,这给常规的测试带来了挑战。本文档将详细介绍如何通过逆向分析前端加密逻辑,并使用Mitmdump工具实现自动化加解密,从而顺利进行渗透测试。 1.1 常见问题场景 请求体和响应体均被加密,密文格式为d1,d2,d3 前端使用复杂的加密算法组合(如AES+RSA) Webpack打包的Vue项目增加了逆向难度 2. JS逆向分析 2.1 加密流程分析 通过浏览器开发者工具分析,发现加密流程如下: d1生成 :使用AES-CBC模式加密原始报文 Key: 随机值n IV: 随机值o d2生成 :使用服务端公钥加密随机值n d3生成 :使用服务端公钥加密随机值o 2.2 解密流程分析 响应体解密流程: 使用客户端私钥解密d2得到n 使用客户端私钥解密d3得到o 使用n和o解密d1得到原始报文 2.3 关键点定位 在控制台搜索"d1:"定位加密函数 下断点分析变量值: e为AES key i为AES iv t为加密前的请求体 公钥获取:通过断点查看rsa值 3. Webpack代码提取 3.1 Webpack通用提取方法 搜索"call"定位入口函数 构建模块加载器框架: 3.2 加密函数提取 提取AES加密相关代码: 3.3 代码补全策略 使用console.log提示缺失函数 按需补全依赖函数 对于无返回值的调用(i("d3b7"))可注释掉 4. Mitmdump自动化加解密 4.1 适用场景 Web网页端防篡改及加解密 App端防篡改及加解密 小程序端防篡改及加解密 4.2 代理架构 二级代理 (仅响应体解密): Burp上游代理指向Mitmdump 三级代理 (请求体和响应体加解密): Burp上游代理指向Mitmdump1 Mitmdump2上游代理指向Burp 4.3 Python脚本模板 4.4 代理设置命令 响应体解密 (二级代理): 请求体和响应体加解密 (三级代理): 4.5 Burp设置 User Options => Upstream Proxy Servers => Add 目标主机:目标网站域名 代理主机:127.0.0.1 代理端口:9090 5. 与其他工具集成 使用sqlmap等工具时,通过代理将流量导向Burp: 6. 关键注意事项 确保获得合法授权后再进行测试 保存完整的JS代码以便后续分析 注意加密算法中可能的自定义修改(如非常规IV长度) 测试过程中记录加解密前后的数据对比 对于复杂的加密逻辑,可能需要分步验证各环节 7. 总结 通过本文介绍的方法,可以有效地处理前端加密场景下的渗透测试问题。关键在于: 准确分析加密逻辑 完整提取加密函数 合理配置代理链 实现自动化加解密流程 这种方法不仅适用于Web应用,也可应用于App和小程序的加密通信分析。