前端 JS 加密与 Buspsuite 的坦诚相待

前端 JS 加密该如何破局/前端 JS 加密与 Buspsuite 的坦诚相待前端 JS 加密测试场景下的困惑在渗透测试过程中经常会遇到 JS 前端加密的场景,假如不借助任何工具的情况下,我们一般是把 JS 代码进行扣取,本地进行加解密生成 Payload,然后在 Burpsuite 里进行 Payload 替换。这种方式就存在一个很明显的问题,那就是在大量的 Fuzz 测试过程中,本地生成再手工替换会消耗大量的时间,这个时候我们就会想,能不能直接在 Burpsuite 前后利用脚本的形式进行加解密操作,让数据在 Burpsuie 里展示的时候已经是加解密后的数据呢?
代理的理解先来看看平常我们渗透场景下 Burpsuite 代理转发数据包的原理不挂 Burpsuite 代理,客户端浏览器直接访问服务器的流程

挂上 Burpsuite 代理之后

现在想要在 Burpsuite 代理转发前后添加脚本进行加解密操作,那分别在客户端浏览器与 Burpsuite 之间、Burpsuite 与服务端服务器之间添加一个代理即可实现。

接下来就是分别实现这些代理功能了。市面上已经有很多优秀的类似代理工具,我们可以使用 Python 脚本进行编写加解密代码然后完成代理实现如上功能,但这样做每次进行不同的网站测试就需要每次都要修改自己的 Python 脚本,扩展性非常差。这里我们可以使用 mitmproxy 来实现我们的需求。
mitmproxy 简介 mitmproxy 是一个免费的 和开源 交互式 HTTPS 代理,可为 HTTP/1、HTTP/2 和 WebSocket 提供支持 SSL/TLS 的交互式拦截代理。相比于其他代理工具其优势有相对于 fiddle 代理工具,它可以跨平台相对于跨平台 charles 代理工具,它开源免费它支持使用 Python 进行二次开发,可以结合业务进行灵活拓展了 mitmproxy 下载地址如下https://mitmproxy.org/mitmproxy安装完成后有如下三个工具 mitmproxy:命令行交互工具 mitmdump:命令行非交互工具 mitmweb:基于 Web 的用户界面在客户端浏览器与 Burpsuite 之间、Burpsuite 与服务端服务器之间的代理也分别有他们名词,分别为下游代理、上游代理。

mitmproxy 一大优势是支持 Python 的二次开发的,而在代理原理图中的请求和响应也依次对应着,mitmproxy 提供 Python 中 API 的 request 和 response。from mitmproxy import ctxfrom mitmproxy.http import HTTPFlow
class MyAddon:def request(self, flow: HTTPFlow):# 这里可以处理请求,比如打印请求信息 ctx.log.info(f"Handling request: {flow.request.pretty_url}")
addons = [MyAddon(),]
mitmproxy 实战使用启动一个服务器,模拟口令登陆功能

在只配置 Burpsuite 代理下登陆抓包

可以看到 password 字段是被加密的,当然这里只是一个简单的 Base64 加密,Burpsuite 也支持直接在 Burpsuite 中直接解密数据,为了演示和后面编写 Python 脚本方便,这里就先假设 Burpsuite 上是不可对 Password 这个字段直接进行解密的。在浏览器客户端到 Burpsuite 之前,我们最常做的处理就是把前端 JS 加密的数据解密到 Burpsuite 里,在 Burpsuite 里直接看到明文的数据。所以在客户端到 Burpsuite 我们走的一条流程就如下

那么我们可以进行编写如下脚本 de.py
from mitmproxy import ctximport base64
class MyAddon():
addons = [MyAddon(),]编写好脚本之后,需要配置好代理,代理配置如下客户端浏览器代理转发给下游代理 代理端口为 7070 下游代理代理转发给 Burpsuite 代理端口为 8080 浏览器代理配置

mitmdump 代理配置 mitmdump -p 7070 -s de.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure

Burpsuite 代理配置

配置好,我们重新进行抓包,可以看到已经可以成功解密数据,直接在 Burpsuite 里进行明文显示了


提交之后,会提示 Login failed!

其实口令 admin、admin 是正确的,只不过我们提交 password 已经是明文的 admin 了,后面还会对这个 admin 进行解密,导致解密后的口令就不再正确了,所以我们还需要在 Burpsuite 把数据提交给服务端服务器之前,重新把数据给加密回来。所以在 Burpsuite 到服务端我们走的一条流程就如下

那么我们可以进行编写如下脚本 en.pyfrom mitmproxy import ctximport base64
class MyAddon():def request(self,flow):# 服务端 hostif flow.request.host=="www.xj.com":req = flow.request.get_text()ctx.log.info("浏览器请求数据 => " + req)result = req.split("&")[2].split("=")[1]ctx.log.info("匹配前 => " + result)data = base64.b64encode(result.encode('utf-8')).decode('utf-8')ctx.log.info("加密后数据 => " + data)#重新组合 payloadnew_req = req.split("password")[0]+"password="+datactx.log.info("最终 payload => " + new_req)flow.request.set_text(new_req)
addons = [MyAddon(),]编写好脚本之后,之前的代理配置不需要改变,额外在 Burpsuite 里配置一个上游代理 Burpsuite 代理配置

mitmdump 代理配置 mitmdump -p 9090 -s en.py --ssl-insecure

配置好后,抓包提交

至此,整个测试流程就跑通了。当然我们这里的只演示了上面请求流程

下面的响应流程我们也可以更具业务需求在脚本的 response 方法里编写相应流程代码即可.
总结
本文结合渗透测试 JS 前端加密情况下的实战场景,利用 mitmproxy 解决了本地加解密测试繁琐的痛点,达到了编写完加解密脚本之后与 Burpsuite 前后建立代理直接在 Burpsuite 进行测试的效果。
评论