part1
点击上方蓝字关注我们
往期推荐
将二进制空间安全设为"星标⭐️"
第一时间收到文章更新
摘要
目前发现的唯一能实现的解决方案是使用Chrome的override功能并配合Burp Suite的PyCript扩展来实现绕过。核心思路是利用override功能修改JavaScript中的加密代码,使其返回原始明文而不是加密请求, 这样就可以在Burp Suite代理中看到解密后的文本。由于服务器是期望收到加密请求的, 因此可以通过配置PyCript来使用与应用程序Javascript代码相同的公钥和加密逻辑对请求进行加密。
实现原理
Chrome浏览器允许编辑Javascript文件并从本地系统加载Javascript文件, 基于这点, 可以使用它来修改应用程序Javascript文件, 使其发送明文请求而不是加密后的请求, 如图:
上面的流程非常简单, Javascript代码会为在浏览器界面中执行的每个操作发送HTTP请求。相同的代码会调用另一个Javascript代码来加密请求并返回加密值。主代码随后会发送加密请求, 并且可以在Burp Suite代理中看到该请求。
在上面的流程中, 攻击者使用Chrome override功能修改了加密代码, 使其返回原始明文而不是加密请求。这样, 就可以在Burp Suite代理中看到解密后的请求。由于服务器期望接收到加密请求, 后面通过配置PySript来使用与应用程序Javascript代码相同的公钥和加密逻辑对请求进行加密。
通过这种方法, 攻击者可以在Burp Suite代理历史记录中看到明文请求, 并且可以在任何地方使用该明文请求。借助PyCript扩展, 服务器端会接收到加密的请求。
实践案例
看下面的案例, 利用拦截代理中的请求, 可以初步确认该应用程序正在使用某种加密算法, 如图:
在查看 JavaScript 代码并搜索如 "encrypt"、"key"、"encryption"、"decrypt" 等关键字后,貌似找到了加密代码, 如下图:
该代码看起来很简单易懂。函数接收一个参数,作为明文数据。然后,代码将 PEM 公钥转换并使用该密钥加密明文数据,最后将加密数据进行 base64 编码并返回。经过研究发现该应用程序使用了 node-forge 库进行加密。
为了确认这段代码确实用于加密,尝试在浏览器中添加断点,并提交请求。当断点被触发时,浏览器停了下来,经过比对可以确认相同的代码用于加密,且函数接收的是明文值。
保持断点不变,攻击者通过控制台调用变量,可以成功获取用于加密的公钥。接下来,研究尝试让该函数返回明文或相同的值,而不是加密后的值。
要修改 JavaScript 代码,需要使用 Chrome 浏览器的override功能。在 "Source" 选项卡中选择 "Overrides",点击 "Select folder for overrides"。
选择文件夹后需要批准,点击允许后便可修改文件。然后找到要编辑的文件。
右键单击该文件,选择 "Save for overrides"。现在回到 "Overrides" 选项卡,可以看到文件已经添加,允许编辑 JavaScript 代码。
编辑 JavaScript 代码,删除加密逻辑,并返回传递给函数的明文值。编辑完成后,按下 ctrl+s 保存。
完成后,需要验证其是否按预期工作。回到应用程序执行某个操作,触发请求发送。在 Burp Suite 中,需要验证请求是否为明文。
现在,可以确认已经成功修改客户端逻辑,并可以在 Burp Suite 代理中看到明文格式的数据。应用程序返回了错误,因为它期望接收到加密数据,而我发送了明文数据。此时,需要使用 PyCript 实现自动加密请求,但在此之前,需要编写与应用程序相同的加密逻辑,以便 PyCript 进行加密。
使用PyCript加密
如前所述,应用程序使用了 node-forge 库进行加密,因此需要按照 node-forge 读文件中的指令进行安装。
var forge = require('node-forge');
const program = require("commander");
const { Buffer } = require('buffer');
program
.option("-d, --data <data>", "Data to process")
.parse(process.argv);
const options = program.opts();
const requestbody = Buffer.from(options.data, 'base64').toString('utf8');
var mypubkey = "-----BEGIN PUBLIC KEY-----MIIwYIYquwxIqzkgkI+oA9oyrbYQIDAQAB-----END PUBLIC KEY-----"
var m = forge.pki.publicKeyFromPem(mypubkey)
var encoutput = m.encrypt(requestbody)
console.log(forge.util.encode64(encoutput));
在上述代码中,使用了 PyCript 所需的格式,并使用 node-forge 对数据进行加密,最后将加密数据用 base64 编码并打印出来。加密方法和逻辑与应用程序的相同,只是根据 PyCript 的要求做了一些修改。
PyCript扩展开源地址:https://github.com/Anof-cyber/PyCript
由于在这个案例中,请求已经是明文,所以只需要加密,不需要解密。因此,这里不需要编写解密代码,但由于扩展要求同时提供加密和解密代码,因此可以提供相同的代码来绕过这些限制。一旦加载脚本,便可以选择请求类型,在这个案例中,只有 JSON 中的值是加密的,所以会选择相应的类型。
最后,需要选择工具类型。因为所有请求都来自浏览器,所以这里需要选择代理并启用自动加密。
回到浏览器执行某个操作,再次验证浏览器是否发送了明文请求。此时没有收到任何无效请求错误,应用程序返回了有效响应,尽管这里的请求是明文格式的。
如果查看 Burp Suite 中的日志记录器,可以看到请求是加密的,即使在代理中看到的是明文请求。这种方法会将明文请求保留在 Burp 代理中,供以后使用,并且不需要私钥来解密。
类似的方案也可以用于移动应用程序。对于移动应用程序,需要像处理网页那样返回明文值。不过,针对移动设备,需要使用 Frida 或直接修改应用程序代码。
往期推荐
点个在看你最好看
原文始发于微信公众号(二进制空间安全):无私钥绕过客户端非对称加密算法
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论