Burp Suite 自定义加解密实战指南

一、前言

‌‌‌‌  在实际渗透测试或接口调试中,我们常常会遇到一些应用对请求参数或响应内容进行了加密处理,常规的抓包分析手段难以直接阅读原始数据。本文将以 Burp Suite 为核心搭配Galaxy插件,介绍如何通过自定义脚本,实现对加密流量的自动解密与加密,从而提升调试效率与还原真实数据的能力

二、适用场景

  • 某某系统需要前端加密参数
  • 接口响应为密文格式
  • 小程序或APP中的通信数据需还原
  • ……(任意流量经过Burp需要二次数据处理的,均可适用)

 

三、原理说明

‌‌‌‌  正常情况下,我们通过Burp代理进行渗透测试时,流量的流转情况如图所示。(下述内容截取Galaxy项目原理)

正常情况下流量流转

‌‌‌‌  而本插件通过 Burp 的 Montoya API 在该流程中添加了 4 个 hook,使得流量流转的情况变成下图这样。

修改后的流量流转

[!流程详细]
①:HTTP请求从客户端到达Burp时被触发。你需要在此处完成请求解密的代码,这样就可以在Burp中看到明文的请求报文。
②:HTTP请求从Burp将要发送到Server时被触发。你需要在此处完成请求加密的代码,这样就可以将加密后的请求报文发送到Server。
③:HTTP响应从Server到达Burp时被触发。你需要在此处完成响应解密的代码,这样就可以在Burp中看到明文的响应报文。
④:HTTP响应从Burp将要返回到Client时被触发。你需要在此处完成响应加密的代码,这样就可以将加密后的响应报文返回给Client。

四、使用示例

1 官方示例

1
2
3
git clone https://github.com/outlaws-bai/GalaxyHttpHooker.git

python312 rsa.py //启动解密http服务

示:
本地0.0.0.0:5000端口启动服务

示:
burp插件配置白名单

‌‌‌‌ 再次抓取数据包,会发现多1个请求步骤进行处理解密操作。

示:
自动解密

1.1 python代码实现

1
hookRequestToBurp,hookRequestToServer,hookResponseToBurp,hookResponseToClient

2 实战示例 md5_Salt 单向加密

下述所以操作,只限于JS加解密研究,并非说明该系统存在问题。

‌‌‌‌  某网站登录接口,使用的是md5+Salt,借助Galaxy插件,将流量发到本地的http 服务端进行二次数据处理,实现参数加密。

示:

1
123456 -> 5dfaf08496a0704f8d18652884a4662a

‌‌‌‌  非默认md5加密,逆向分析js加密步骤,调试发现用了md5+Salt加密。分析了当前js未进行魔改,就是原版的md5。

示:
js调试

示:
md5加密js

‌‌‌‌  本次测试,为方便后续遇到的一些复杂的js情况,直接把代码扣到本地文件,直接调用加密参数。根据python脚本实现的功能接口,使用Node.js起HTTP服务,方便后续环境中如果遇到复杂的js函数,可以直接调用函数。

示:

2.1 node.js代码实现

‌‌‌‌  由于是单向加密,根据Burp Suite 和Galaxy的流程图,我们只需要在数据提交到server时(②步骤),进行处理即可,其他默认返回即可。
‌‌‌‌  通过将加密相关的函数扣本地input.js文件,然后调用加密函数,替换参数。

示:

示:
数据二次处理加密

‌‌‌‌  后面即可正常按照平时流程进行爆破密码。

2.2 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
const express = require('express');
const bodyParser = require('body-parser');
const app = express();

//自定义加密js.......
const fs = require('fs');
eval(fs.readFileSync('./input.js', 'utf-8'));

app.use(bodyParser.json({ type: '*/*' }));

// 1. 客户端到达Burp时(如需解密,在此处解密代码)
app.post('/hookRequestToBurp', (req, res) => {
res.json(req.body);
});

// 2. Burp将要发送到Server服务时(二次处理请求,加密内容参数)
app.post('/hookRequestToServer', (req, res) => {
try {
console.log(`传入数据:\n${JSON.stringify(req.body)}`)

const contentBase64 = req.body.contentBase64;
const decodedContent = Buffer.from(contentBase64, 'base64').toString('utf-8'); //解密

// 使用 URLSearchParams 解析内容
const urlParams = new URLSearchParams(decodedContent);
console.log(urlParams.toString()); // 得到类似:nadmin_name=1&nadmin_password=xxx&keeplanding=1

// 获取具体的值
const adminPassword = urlParams.get('nadmin_password');
console.log(`nadmin_password参数:${adminPassword}`)


//自定义加密
combined = hex_md5(hex_md5(adminPassword + 'ncsp951753456852jdkmd') + adminPassword + 'zseqsc951753mhtvhu');
console.log(`nadmin_password参数加密后:${combined}`)


// 修改参数
urlParams.set('nadmin_password', combined);

// 转换回 x-www-form-urlencoded 格式的字符串
const encodedContent = urlParams.toString(); // 得到类似:nadmin_name=1&nadmin_password=xxx&keeplanding=1
console.log(`封装后的内容:${encodedContent}`);


const base64Encoded = Buffer.from(encodedContent, 'utf-8').toString('base64'); //解密

// 替换原内容
req.body.contentBase64 = base64Encoded;


console.log(`二次处理数据:\n${JSON.stringify(req.body)}`)
res.json(req.body);
} catch (err) {
res.status(500).json({ error: '加密处理失败', details: err.message });
}
});

// 3. Server到达Burp时(如需解密,在此处解密代码)
app.post('/hookResponseToBurp', (req, res) => {
res.json(req.body);
});

// 4. Burp将要返回到客户端时
app.post('/hookResponseToClient', (req, res) => {
res.json(req.body);
});

const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server running on http://0.0.0.0:${PORT}`);
});

五、核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const express = require('express');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json({ type: '*/*' }));

// 1. 客户端到达Burp时(如需解密,在此处解密代码)
app.post('/hookRequestToBurp', (req, res) => {
res.json(req.body);
});

// 2. Burp将要发送到Server服务时(二次处理请求,加密内容参数)
app.post('/hookRequestToServer', (req, res) => {
res.json(req.body);
});

// 3. Server到达Burp时(如需解密,在此处解密代码)
app.post('/hookResponseToBurp', (req, res) => {
res.json(req.body);
});

// 4. Burp将要返回到客户端时
app.post('/hookResponseToClient', (req, res) => {
res.json(req.body);
});

const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server running on http://0.0.0.0:${PORT}`);
});

参考

https://github.com/outlaws-bai/Galaxy