背景 在渗透过程中,经常会遇到参数和返回值加密的情况
比如
请求 和 返回如下
那么我们如何找寻加密方式和明文参数呢 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} ` ); });