我的GitHub
0%

无星的渗透之旅速成篇(十二)-Burp参数加解密

背景

在渗透过程中,经常会遇到参数和返回值加密的情况

比如

请求 和 返回如下

那么我们如何找寻加密方式和明文参数呢

1. 代码审计

打开F12通过搜索查找接口所在代码位置

自己添加一行打印并保存,就能看到明文参数

2.查看签名逻辑和加密逻辑

这个需要各位通过断点自行分析

一般前端的加密库无非是CryptoJSJSencrypt

可自行调用其中的方法去加密

3. 参数分析

从请求参数我们可以看出,有加密以后的参数值,还有一个sign

公钥加密,私钥解密

私钥签名,公钥验签

因此我们可以知道,客户端一定至少有一个公钥一个私钥(不是一对)

4. 自行写出加密算法将明文加密并将加密后的参数通过burp请求发送给后端看是否能成功响应

都成功以后,我们就要引入工具在Burp中来进行明文的加解密

autoDecoder

autoDecoder

releases下载支持的java版本

下载以后在burp中导入插件

导入以后的效果

我这里使用的为0.53版本 以下以0.53为例

autoDecoder的使用说明

吐槽:文档写的稀烂,第一次使用的人看着一头雾水

本文不讨论自带加解密的使用场景

本文不讨论自带加解密的使用场景

本文不讨论自带加解密的使用场景

1.保存设置

修改完配置以后,一定要点保存设置

保存到哪呢?文件名是什么呢?

答案是保存到burp安装目录下

1
D:\Safety\BurpSuite V2024.1.1\BurpSuite\autoDecoder.properties

真离谱啊,项目什么说明都没有

2. 各选项解析

2.1 是否加密

不加密就选 不对请求加密
加密就选 接口加解密

2.2 对数据头处理

1
2
3
4
5
6
7
8
9
10
11
12
POST /c2dm/register3 HTTP/1.1
Authorization: AidLogin 3871712111200470812:4760107678655134024
app: xx.xx.xx
gcm_ver: 220920023
User-Agent: Android-GCM/1.5 (star2qltechn PQ3B.190801.12191611)
Content-Length: 470
content-type: application/x-www-form-urlencoded
Host: xx.xx.xx
Connection: close
Accept-Encoding: gzip, deflate, br

X-subtype=123&X-X-subscription=123&sender=123&X-X-subtype=745476177629&X-app_ver=123&X-osv=28&X-cliv=iid-123&X-gmsv=123&X-appid=co9n94L-3-w&X-scope=GCM&X-subscription=123&X-app_ver_name=22.09.20+%28040800-%7B%7Bcl%7D%7D%29&app=com.google.android.gms&device=123&app_ver=123&info=I4jR59gyCOUeoOhBO1boBVyF78BVQxk&gcm_ver=123&plat=0&cert=123&target_ver=31

勾选以后,给接口发送的明文中就会带

1
2
3
4
5
6
7
8
9
10
POST /c2dm/register3 HTTP/1.1
Authorization: AidLogin 3871712111200470812:4760107678655134024
app: xx.xx.xx
gcm_ver: 220920023
User-Agent: Android-GCM/1.5 (star2qltechn PQ3B.190801.12191611)
Content-Length: 470
content-type: application/x-www-form-urlencoded
Host: xx.xx.xx
Connection: close
Accept-Encoding: gzip, deflate, br

不勾选就不带

2.3 请求不同加解密

勾上就完事了

加密解密分别请求不同的接口

2.4 模块控制

选中的这些模块请求可以走加解密接口过

2.5 底下的明文关键字和密文关键字我觉得写的很绕,没看明白

2.6 加解密接口

  • 注意事项: postman的请求样式和真实burp转发的请求略有不同

以下为postman的请求样式

py版

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
from flask import Flask, Response, request
import base64, hashlib, json
from pyDes import *
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5, AES
from Crypto.Util.Padding import pad
from Crypto.Hash import SHA256
from Crypto.Signature import pkcs1_15
from datetime import datetime
from base64 import b64decode

app = Flask(__name__)

def encrypt_func(data):
# 1. 创建返回值字典
request_param = {}
return request_param

@app.route("/encode/json", methods=["POST"])
def encrypt():
# 获取 JSON 格式的数据
data = request.get_json()
if not data:
return "无效的 JSON 数据", 400
# 加密逻辑
request_param = encrypt_func(data)

return request_param


@app.route("/decode/json", methods=["POST"]) # 不解密
def decrypt():
data = request.get_json()
if not data:
return "无效的 JSON 数据", 400

try:
# 1. 使用private_key解密encrypt_key
rsa_key = RSA.importKey(private_key)
cipher = PKCS1_v1_5.new(rsa_key)
encrypt_key = b64decode(data["encrypt_key"])
decrypted_aes_key = cipher.decrypt(encrypt_key, None).decode("utf-8")
print("解密后的AES密钥:", decrypted_aes_key)
# 2. 使用解密后的AES密钥解密response_biz_content
cipher = AES.new(decrypted_aes_key.encode("utf-8"), AES.MODE_ECB)
encrypted_content = b64decode(data["response_biz_content"])
decrypted_content = cipher.decrypt(encrypted_content)
# 去除填充
unpad = lambda s: s[: -ord(s[-1:])]
decrypted_content = unpad(decrypted_content.decode("utf-8"))

return {
"status": "success",
"aes_key": decrypted_aes_key,
"decrypted_content": decrypted_content,
}
except Exception as e:
return {"status": "error", "message": str(e)}, 400

if __name__ == "__main__":
app.debug = True # 设置调试模式,生产模式的时候要关掉debug
app.run(host="0.0.0.0", port="8888")

真实的burp数据转发

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
from flask import Flask, Response, request
import base64, hashlib, json
from pyDes import *
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5, AES
from Crypto.Util.Padding import pad
from Crypto.Hash import SHA256
from Crypto.Signature import pkcs1_15
from datetime import datetime
from base64 import b64decode

app = Flask(__name__)

def encrypt_func(data):
# 1. 创建返回值字典
request_param = {}
return request_param

def decrypt_func(data):
# 1. 使用private_key解密encrypt_key
return request_param

@app.route("/encode", methods=["POST"])
def encrypt2():
# 获取 JSON 格式的数据
param = request.form.get("dataBody") # 获取 post 参数
param_headers = request.form.get("dataHeaders") # 获取 post 参数
param_requestorresponse = request.form.get("requestorresponse") # 获取 post 参数

# 我们要做的事
# 1. 创建返回值字典
request_param = encrypt_func(data)

if param_requestorresponse == "request":
return param_headers + "\r\n\r\n\r\n\r\n" + json.dumps(request_param)
return json.dumps(request_param)


@app.route("/decode", methods=["POST"]) # 不解密
def decrypt2():
param = request.form.get("dataBody") # 获取 post 参数
param_headers = request.form.get("dataHeaders") # 获取 post 参数
param_requestorresponse = request.form.get("requestorresponse") # 获取 post 参数

# 将数据转换为字符串
data = json.loads(param)
try:

decrypted_content = decrypt_func(data)
# 去除填充
unpad = lambda s: s[: -ord(s[-1:])]
# 如果返回解析里有中文,一定要用utf-8编码以下,不然变成unicode展示了
decrypted_content = unpad(decrypted_content.decode("utf-8"))
decrypted_content1 = json.loads(decrypted_content)

# 给data添加结果就行
data["decrypted_content"] = decrypted_content1
# decrypt_param = json.dumps(data)

if param_requestorresponse == "request":
return param_headers + "\r\n\r\n\r\n\r\n" + json.dumps(data, ensure_ascii=False)
return json.dumps(data)
except Exception as e:
return {"status": "error", "message": str(e)}, 400


if __name__ == "__main__":
app.debug = True # 设置调试模式,生产模式的时候要关掉debug
app.run(host="0.0.0.0", port="8888")

其实基本都是前端加密,有时候用py反而麻烦,直接同宗同源的js撸出来就是了
以下为js版

1
2
3
4
5
6
7
pnpm init
pnpm add express body-parser
# 视情况添加算法库
pnpm add crypto-js
pnpm add jsencrypt
pnpm add sm-crypto

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const sm2 = require('sm-crypto').sm2;

const app = express();

// 添加解析 JSON 和 urlencoded 的支持
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// 加密数据的函数
const encryptData = (data) => {
const param = JSON.parse(data);
const wait = JSON.stringify(param)
// 密钥从源码扒
const enc = sm2.doEncrypt(wait, 'xxxxxx', 1);
return enc;
};

// post请求加密路由
app.post('/encode', (req, res) => {
const requestBody = req.body.dataBody;
const requestHeaders = req.body.dataHeaders;
console.log('要加密的数据:', requestBody);
if (!requestBody) {
return res.send(req.body)
// return res.status(400).send('缺少 dataBody 参数');
}

const encryptedData = encryptData(requestBody);
if (requestHeaders) {
const ress = requestHeaders + "\r\n\r\n\r\n\r\n" + encryptedData
console.log('加密后的数据1:', ress);
res.send(ress);
} else {
console.log('加密后的数据2:', encryptedData);
const result = { "encrypt": encryptedData }
res.send(result);
}
});

// get请求加密路由
app.post('/encode/get', (req, res) => {
console.log(req);
const requestHeaders = req.body.dataHeaders;
// 提取 encrypt 参数
const match = requestHeaders.match(/encrypt=([^&]+)/);
if (!match) {
return res.status(400).send('未找到 encrypt 参数');
}
try {
// 解码 URL 编码的参数
const decodeParam = decodeURIComponent(match[1]);
console.log('解码后的参数:', decodeParam);

// 加密参数
const encryptedData = encryptData(decodeParam);

// 构建响应
if (requestHeaders) {
// 替换原始请求中的 encrypt 参数值
const newRequestLine = requestHeaders.replace(/encrypt=[^&]+/, `encrypt=${encryptedData}`);
console.log('加密后的请求:', newRequestLine);
res.send(newRequestLine);
} else {
const result = { "encrypt": encryptedData };
res.send(result);
}
} catch (error) {
console.error('处理请求时出错:', error);
res.status(500).send('处理请求时出错: ' + error.message);
}
});

// 不解密路由
app.post('/decode', (req, res) => {
const param = req.body.dataBody;
res.send(param);
});

// 启动服务器
const port = 8888;
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});
我是阿星,阿星的阿,阿星的星!