从一次前端js加密再到mitm中间人脚本
从一次前端 js 加密再到 mitm 中间人脚本
0X00 前端 JS 加密的加解密
1、前因
- 在一次渗透测试中,项目经理给了一批小程序的资产,在挖洞的过程中,发现了一个流量加密的点,因为以前看过很多文章通过分析 js 文件来实现加解密数据,自己也想来实战一下通过分析 js 文件来实现加解密
- 谢公子的文章:浅析绕过 js 加密
- 酒仙桥六号部队的文章:前端加密加签之 sqlmap 自动化测试
- 在 Burpsuite 中可以发现数据包中 POST 的 body 字段和响应包的 body 字段数据都是加密的,想到公司大佬的一句话“只要是前端加密,我都能给你解密”
2、拖下小程序源码
- 思路过程:adb 连接模拟器 -> 找到小程序的源码包 wxapkg -> 使用 adb pull 进行拉取到本地 -> 通过 unpack 工具来解出源码,具体的小程序脱包教程以及工具文章,感兴趣的大哥可以从雷神众测上查看Poc Sir的文章
- xuedingmiaojun 大佬的不带 GUI 界面:wxappUnpacker
- xuedingmiaojun 大佬的带 GUI 界面:mp-unpack(实测此工具能较完善解析 wxapkg 包)
3、快速分析源码
- 使用 Sublime 打开压缩包的文件,来进行源码的查看
- 从刚才抓取的 Burpsuite 的数据包中的请求连接,全局匹配对应的句子,发现了在/pages/myInfo 目录下的 A.api.js 文件进行了 POST 请求
- 跟进对应的 js 文件,发现通过 t.request 方法来发送一个 POST 请求
- 跟进 t.request 方法,发现是导入/utils 目录下的 request 模块
- 跟进 request.js 文件,发现默认导出为 a,a 又通过函数 p 来进行赋值,在这个过程中,又通过引入 o.default 来进行传参
- 跟进 o.default,发现是通过导入/miniprogram_npm/wx-weapp-tool/index 下的 index 模块来实现的
- 跟进 index.js 文件,发现默认导出为 y,y 又通过 g 去赋值,搜索包含 g 的参数或者函数,发现 g 函数,g 函数中有对 o 的处理,通过 c.default.encrypt 来进行加密
- 搜索 c 的相关函数或者其他变量,发现是导入 d2jk-share-templates 目录下的 aes 模块
- 跟进 aes.js 文件,发现此文件就是最后的加密函数,以及加解密方法为 AES 加密结合 Base64 加密,可以通过导入 crypto-js 库来实现
- 将此文件进行导出,重新定义为 ase.js 文件,在终端进行加解密尝试,发现解密成功
- 对响应包的内容进行解密,发现了身份证以及手机号
- 在 lo 出数据后,发现通过黏贴密文,再输入 key 的方式效率实在是太低了,准备打算写一个自动化的中间人脚本来实现此过程
0X01 mitm 中间人脚本编写
1、需求前提
- 实现原理图
所需工具
- python 3.6
- mitmproxy 5.0.1
- Burpsuite
参考文章推荐
2、实现过程
- js 文件的模板函数导出,方便外部的调用
1 | module.exports.enc = function (data) { |
- 加解密函数的编写
- cmd 为要执行的命令,使用 node 的-e 参数,require 调用模块以及模块里面的参数
- pipeline 获得 os.popen 后的内容
- 最后返回 result
1 | def enc(data): |
mitm 第一层代理的编写
需要接受来自客户端的加密请求,可以通过
mitmdump -p 8081
去监听端口,客户端设置 8081 端口进行代理流量接收来自客户端的加密数据,进行解密,然后发送给 Burpsuite
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def request(self, flow: http.HTTPFlow):
def enc(data):
cmd = 'node -e "require(\\"./ase.js\\").enc(\'%s\')"' % (data)
pipeline = os.popen(cmd)
result = pipeline.read()
return result
def dec(data):
cmd = 'node -e "require(\\"./ase.js\\").dec(\'%s\')"' % (data)
pipeline = os.popen(cmd)
result = pipeline.read()
return result
req_data = flow.request.get_text()
if req_data:
print("req:"+req_data)
print("解密:"+dec(req_data))
flow.request.set_text(dec(req_data))- 发送来自 Burpsuite 的解密数据,进行加密,然后发送给客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def response(self, flow: http.HTTPFlow):
def enc(data):
cmd = 'node -e "require(\\"./ase.js\\").enc(\'%s\')"' % (data)
print(cmd)
pipeline = os.popen(cmd)
result = pipeline.buffer.read().decode(encoding="utf-8") # 因为中文编码问题会报错,这里需要进行utf-8编码
return result
def dec(data):
cmd = 'node -e "require(\\"./ase.js\\").dec(\'%s\')"' % (data)
pipeline = os.popen(cmd)
result = pipeline.buffer.read().decode(encoding="utf-8") # 因为中文编码问题会报错,这里需要进行utf-8编码
return result
resp_data = flow.response.get_text()
if resp_data:
print(resp_data.strip('\n'))
flow.response.set_text(dec(resp_data.strip('\n')))设置上游代理为 Burpsuite,进行数据包的转发
mitmdump -p 8081 -m upstream:http://127.0.0.1:8080 -s min.py -k
- -m 为指定上游代理模块,这里为 Burpsuite 监听的端口
- -k 为忽略证书的错误,同时也需要在客户端中安装 mitm 的证书(安装 mitm 的证书在设置代理的情况下访问https://mitm.it下载即可)
- -s 为指定使用的脚本
发现已经可以正常的对请求报进行解密
Burpsuite 的设置
- 监听 8080 端口,接收来自 mitm 第一层代理的数据
- 设置上层代理为 mitm 第三层代理,进行数据包的转发
mitm 第三层代理的编写
- 接收来自 Burpsuite 的解密后的数据,可以通过
mitmdump -p 8088
去监听端口 - 接收来自 Burpsuite 的解密数据,进行加密,然后发送给服务端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20def request(self, flow: http.HTTPFlow):
def enc(data):
cmd = 'node -e "require(\\"./ase.js\\").enc(\'%s\')"' % (data.strip('\n'))
print(cmd)
pipeline = os.popen(cmd)
result = pipeline.buffer.read().decode(encoding="utf-8")# 因为中文编码问题会报错,这里需要进行utf-8编码
return result
def dec(data):
cmd = 'node -e "require(\\"./ase.js\\").dec(\'%s\')"' % (data)
pipeline = os.popen(cmd)
result = pipeline.buffer.read().decode(encoding="utf-8")# 因为中文编码问题会报错,这里需要进行utf-8编码
return result
req_data = flow.request.get_text()
if req_data:
print(req_data)
print("sdasdasdasa")
req_data = req_data.replace('"','\\"')
print("req:"+req_data)
print("加密:"+enc(req_data))
flow.request.set_text(enc(req_data))- 发送来自服务端的加密数据,进行解密,然后发送给 Burpsuite
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18def response(self, flow: http.HTTPFlow):
def enc(data):
cmd = 'node -e "require(\\"./ase.js\\").enc(\'%s\')"' % (data)
print(cmd)
pipeline = os.popen(cmd)
result = pipeline.buffer.read().decode(encoding="utf-8")# 因为中文编码问题会报错,这里需要进行utf-8编码
return result
def dec(data):
cmd = 'node -e "require(\\"./ase.js\\").dec(\'%s\')"' % (data)
pipeline = os.popen(cmd)
result = pipeline.buffer.read().decode(encoding="utf-8")# 因为中文编码问题会报错,这里需要进行utf-8编码
return result
resp_data = flow.response.get_text()
if resp_data:
print("req:"+resp_data)
print("解密:"+dec(resp_data))
print(resp_data.strip('\n'))
flow.response.set_text(dec(resp_data.strip('\n')))- 设置转发给服务器,进行数据包的转发
mitmdump -p 8088 -s min.py -k
- 使用 Burpsuite 的 Repeater 模块进行测试,发现已经可以正常加解密了
- 接收来自 Burpsuite 的解密后的数据,可以通过
0X02 总结
这次的过程中也存在着很多问题,请各位路过的大哥大姐大佬等不吝指导,后续想集成一个 Burpsuite 插件,可以自定义需要加解密的目标地址方便渗透测试加解密,只需要导入加密的 js 文件即可,各个论坛网站上也有各个大佬开发的插件脚本,想后续继续深入学习