背景 在渗透过程中,经常会遇到参数和返回值加密的情况
比如
请求 和 返回如下
那么我们如何找寻加密方式和明文参数呢 1. 代码审计 打开F12
通过搜索查找接口所在代码位置
自己添加一行打印并保存,就能看到明文参数
2.查看签名逻辑和加密逻辑 这个需要各位通过断点自行分析
一般前端的加密库无非是CryptoJS
和JSencrypt
可自行调用其中的方法去加密
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, requestimport base64, hashlib, jsonfrom pyDes import *from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_v1_5, AESfrom Crypto.Util.Padding import padfrom Crypto.Hash import SHA256from Crypto.Signature import pkcs1_15from datetime import datetimefrom base64 import b64decodeapp = Flask(__name__) def encrypt_func (data ): request_param = {} return request_param @app.route("/encode/json" , methods=["POST" ] ) def encrypt (): 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 : 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) 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 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, requestimport base64, hashlib, jsonfrom pyDes import *from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_v1_5, AESfrom Crypto.Util.Padding import padfrom Crypto.Hash import SHA256from Crypto.Signature import pkcs1_15from datetime import datetimefrom base64 import b64decodeapp = Flask(__name__) def encrypt_func (data ): request_param = {} return request_param def decrypt_func (data ): return request_param @app.route("/encode" , methods=["POST" ] ) def encrypt2 (): param = request.form.get("dataBody" ) param_headers = request.form.get("dataHeaders" ) param_requestorresponse = request.form.get("requestorresponse" ) 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" ) param_headers = request.form.get("dataHeaders" ) param_requestorresponse = request.form.get("requestorresponse" ) data = json.loads(param) try : decrypted_content = decrypt_func(data) unpad = lambda s: s[: -ord (s[-1 :])] decrypted_content = unpad(decrypted_content.decode("utf-8" )) decrypted_content1 = json.loads(decrypted_content) data["decrypted_content" ] = decrypted_content1 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 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 ();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; }; 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 ) } 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); } }); app.post ('/encode/get' , (req, res ) => { console .log (req); const requestHeaders = req.body .dataHeaders ; const match = requestHeaders.match (/encrypt=([^&]+)/ ); if (!match) { return res.status (400 ).send ('未找到 encrypt 参数' ); } try { const decodeParam = decodeURIComponent (match[1 ]); console .log ('解码后的参数:' , decodeParam); const encryptedData = encryptData (decodeParam); if (requestHeaders) { 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} ` ); });