渗透测试请求加解密及签名解决方案
简介......
不是所有加密都能过 WAF 的,有些在所有都走的网关加密,在安全设备里会做解密。
目录
Web
熟练用 DeveloperTools。
https://alan.norbauer.com/articles/browser-debugging-tricks#logpoints--tracepoints
https://sspai.com/post/85686
调试 JS:
有时无法格式化,文件大在线工具也不支持,可以在“源码->片段”选项卡中粘贴格式化查看。
如何调试现有页面 JS?打开开发者工具,找到源代码选项卡下的 Override(覆盖),勾选后刷新页面(不确定是否需要刷新),就可以编辑对应 JS,编辑完保存后会再指定文件夹中写入编辑后的脚本,后续网站则使用编辑后的脚本执行 JS。
https://juejin.cn/post/7235663093748940837
分析加密特征-了解常见的加密特征
加密:对称或非对称对传输数据做加密。常见对称加密(AES/DES/SM4)的加密结果大多都是十六进制或者 Base64 编码,非对称加密(RSA/SM2)每次加密结果不同,对称每次加密结果相同。有些加密结果传递的可能是二进制数据,而不是加密结果。
哈希:哈希摘要算法(MD5/SHA-1/SHA-2/SM3)对整个请求包做签名。有的也有用 HMAC,这个 HCMA 也可以通过 Key 来校验数据。
编码:URL、Base、Unicode
定位加密位置(寻找加密方法)
手动调试阶段加解密推荐使用离线工具 CyberChef。
关键字定位:
- 全局搜索加密库关键字,通用关键字 encrypt,如对称加密:sm4、ecb、cbc、mode,非对称加密:sm2、rsa
- 全局搜索加解密关键字
- 搜索 URL Pattern,找接口
- 搜索加密数据参数名
- 有些会用 Axios 拦截器,搜 interceptor,interceptor.request.use,interceptor.response.use
断点分析:
对断点上下堆栈进行回溯上下文分析,找到加密前获取的参数,或者加密后的参数名,查看参数值是否匹配。
- 请求断点:XHR/fetch Breakpoints
- 网络面板选中具体请求,找到启动器面板,通过请求调用堆栈回溯
- JS 表达式断点:对指定 JS 指定行数断点
- 事件断点:如 mouseclick
反调试:
- 遇到无限 Debugger 怎么解决(可以拿 https://www.grab4k.com/ 练手)
https://www.52pojie.cn/thread-1871058-1-1.html
https://www.52pojie.cn/thread-1868749-1-1.html
人工手动修改
加密数据修改:
- 对于加密的数据,如果是对称加密,可以自己编写脚本搞个 Flask 做代理服务器对数据进行加解密转发。如果是非对称每次测试都要先拿到明文在篡改,接着手工加密发。
- 要么就是在浏览器加密数据前在调试过程中对参数修改。比如断点在加密前的参数,在 Console 对变量进行修改,或者在作用域处修改变量值。
半自动化修改
这两种都需手动操作,流程繁琐。于是有人就想在参数被加密前,让浏览器将明文参数通过 Ajax 发送 BurpSuite,由 BurpSuite 修改完后响应给浏览器,再进行后面的加密步骤。这大家就是半自动化方案。
var xhr = new XMLHttpRequest(); xhr.open("POST", "http://127.0.0.1:28080/REQUEST, false) xhr.send(packageData); // 发送明文参数 packageData packageData = xhr.responseText; // 得到修改后的参数重新修改原有参数值
更细致的描述来说,通过 JS 文件定位到加密方法,在加密前将数据 Ajax 发送到到本地启动的服务器 127.0.1:28080/REQUEST,挂上代理转到 BurpSuite,改完后发出请求到 127.0.0.1:28080,由它将修改后的明文数据作为响应返回,最后参数被重新赋值传入。
JS-Forward 整个流程架构是。
PS:本地启一个 HTTP 服务不优雅,不如直接做成 BurpSuite 插件。这样做的目的是为了优化用户体验,此时https://github.com/f0ng/autoDecoder(用法https://www.t00ls.com/viewthread.php?tid=68439)产生,整合了常见加解密算法设置,直接在 BurpSuite 里对各个模块请求解密,如果想像 js-forwarded 一样也可以写 Flask 脚本来自定义需求。
为了将这段 JS 插入到加密参数的上下文中,可以用重写,一旦原有的 JS 有变动,会缓存下来使用本地编辑后的 JS。
特别要注意的一点是修改浏览器 JS 时,Sources -> Overrides 要先选择一个目录用来存放修改后的 JS(会以域名创建一个文件夹),这个目录归档时最好放在测试目录中乱放不方便找,不管浏览器重新加载关闭后重新打开修改过的内容依旧存在。需要注意的是代码格式化后无法修改,只有文件落地后格式化的代码才能修改。
不开启就仅仅在当前修改生效,浏览器重新加载或关闭后修改丢失,又要重新改很麻烦的。
要是没法用重写呢?在工作中遇到 CefSharp 编写的客户端,虽然启用了开发者模式,但重写功能没法选择要保存 JS 的位置。这时候只能选择抓包时修改 JS,我的做法是先选择好 JS 存放到位置,再通过 BurpSuite 抓取 JS,使用 Match/Replace 功能进行替换。在操作的时候要是没法修改成功,需要注意 JS 响应是不是被缓存。
全自动化修改
mitmproxy
最近又流行一种加解密方案,根本逻辑还是先分析出到底是什么加密算法,再去写个代理服务器处理请求响应加解密,相比以前用 Flask 写个代理服务器它可以处理 HTTPS,这是优势。
使用 NodeJS 写加密算法代码 JS 脚本,再用 Python 库 execjs 执行 JS,最后通过 mitmdump(是 mitmproxy 工具集其中的一个工具)代理加载 Python 脚本完成请求自动化加解密。
浏览器(请求开始) ↓ mitmdump1(解密请求) ↓ BurpSuite(修改明文请求并发送) ↓ mitmdump2(将请求请求加密发送,将收到的响应密文解密返回) ↓ BurpSuite(修改明文响应并返回) ↓ mitmdump1(将明文响应加密返回) ↓ 浏览器(请求结束)
如果不想写脚本加密响应,可以把前端处理后端数据的逻辑搞清楚,再去篡改它们的控制流,让前端直接处理我们返回的明文。
参考文章:
- https://xz.aliyun.com/t/13218
https://xz.aliyun.com/t/16673?time__1311=Gui%3DYKGILDOD%2FD0ltGkDumD9Qtf2aaPpD - https://mp.weixin.qq.com/s?__biz=MzkzNTcwOTgxMQ==&mid=2247484397&idx=1&sn=67bd315311e12bdf2011bde87566d3c8
https://mp.weixin.qq.com/s/L5GD6PwivRG-1IfgpSCfEw - https://xz.aliyun.com/t/15051
https://xz.aliyun.com/t/15252
油猴
浏览器插件更为方便,直接 Hook。
https://github.com/0xsdeo/Hook_JS
App
和 Web 分析思路类似,只是操作不同。
遇到原生 App 加密用 Frida Hook 即可,如果是 Android 没加固还能直接看加密代码。
另一种情况是 H5 开发的应用,直接抓包会发现是有请求 JS,在 JS 里面写的加密,这种情况和 Web 一样,直接 Hook 明文转发即可。
最后一种是混合开发,是 JS 打包到 App 里了通过本地调用,Android 通过翻包文件,或者 iOS 用爱思助手图形化工具查看安装包所在位置的本地文件。Objection 能够自动化查找
使用 Frida Hook 对方法进行重写。
等后续有案例再更新分析过程把,大概率使用 mPaaS 做案例。
最近更新:
发布时间: