一次前端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 加密流程分析
通过浏览器开发者工具分析,发现加密流程如下:
- 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"定位入口函数
- 构建模块加载器框架:
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 代码补全策略
- 使用console.log提示缺失函数
- 按需补全依赖函数
- 对于无返回值的调用(i("d3b7"))可注释掉
4. Mitmdump自动化加解密
4.1 适用场景
- Web网页端防篡改及加解密
- App端防篡改及加解密
- 小程序端防篡改及加解密
4.2 代理架构
-
二级代理(仅响应体解密):
- Burp上游代理指向Mitmdump
-
三级代理(请求体和响应体加解密):
- 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 代理设置命令
- 响应体解密(二级代理):
mitmdump -p 9090 -s ./test.py --ssl-insecure
- 请求体和响应体加解密(三级代理):
# 第一个终端(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设置
- 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. 关键注意事项
- 确保获得合法授权后再进行测试
- 保存完整的JS代码以便后续分析
- 注意加密算法中可能的自定义修改(如非常规IV长度)
- 测试过程中记录加解密前后的数据对比
- 对于复杂的加密逻辑,可能需要分步验证各环节
7. 总结
通过本文介绍的方法,可以有效地处理前端加密场景下的渗透测试问题。关键在于:
- 准确分析加密逻辑
- 完整提取加密函数
- 合理配置代理链
- 实现自动化加解密流程
这种方法不仅适用于Web应用,也可应用于App和小程序的加密通信分析。