JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

admin 2025年6月26日00:41:57评论3 views字数 10235阅读34分7秒阅读模式

0x01 前言

在渗透测试中,前端加密的请求数据常常增加分析难度,传统的手动逆向加解密效率低下且耗时。JsRpc通过WebSocket与客户端通信,结合Burp Suite的插件(如Galaxy)或代理工具(如mitmproxy),可实现请求与响应的自动加解密,极大提升测试效率。本文整合两篇教程,详细解析JsRpc与Burp Suite联动的实现原理与步骤,涵盖环境搭建、函数注册、脚本配置及实战效果展示,帮助安全从业者快速掌握自动化加解密技术。

练手地址:

https://github.com/0ctDay/encrypt-decrypt-vulsJsRpc:https://github.com/jxhczhl/JsRpc

参考文章:https://xz.aliyun.com/news/16886

https://xz.aliyun.com/news/14689

现在只对常读和星标的公众号才展示大图推送,建议大家把渗透安全HackTwo“设为星标”,否则可能就看不到了啦!

末尾可领取挖洞资料文件 #渗透安全HackTwo

0x02 漏洞详情

JsRpc基本使用

首先观察一下原始的数据包

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

可以看到除了请求体需要解密,还有请求头中的timestamp、requestId、sign 需要实时更新,所以请求包中总共有四个地方需要处理,由于是直接只用JsRpc,那么就只需要找到对应的处理位置然后调用即可,不需要弄清楚具体的处理逻辑

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

可以看到就是图中的几个地方处理的,具体逻辑就不分析了,主要是学会使用jsrpc

首先把这几个函数先提升到全局,需要先断点让其加载到作用域

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

然后在控制台执行下面语句提升至全局作用域

window.requestId=p//requestIdwindow.v1 = v//函数vwindow.sign=a.a.MD5//签名signwindow.l=lwindow.d=d
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

然后注入jsrpc中的js文件JsEnv_Dev.js ,注意注js的时候断点就得停止了

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

然后启动jsrpc服务端

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

再客户端连接

var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

连接成功后服务端会提示新上线….然后就是将函数注册进去,即我们要怎么处理值

demo.regAction("encode",function (resolve,param) {    n=JSON.stringify(v1(param))    var request = l(n)    var time = Date.parse(new Date);    var id=requestId()    var sg = sign(n+id+time).toString()    var data={"time":"","id":"","sign":"","request":""}    data["time"]=time.toString()    data["id"]=id    data["sign"]=sg    data["request"] = request    resolve(data);})

上面是加密,下面是解密

demo.regAction("decode"function (resolve,param) {    //这样添加了一个param参数,http接口带上它,这里就能获得    var response = d(param)    resolve(response);})
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

此时就可以测试一下jsrpc处理是否能成功

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)
http://127.0.0.1:12080/go?group=zzz&action=encode&param={"password":"123123","username":"asd","validCode":"ycpa"}

可以看到加密是没有任何问题的,zzz就是加入的组和你一开始连接的时候相同即可,action 即你注册的加密函数,param 就是你要处理的参数,看看解密

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

也是能够正常处理的

JsRpc联动burp

联动burp需要借助mitmproxy写脚本,或者借助其它一些burp插件也行,这里就用mitmproxy了,脚本借助gpt弄几下即可

import requestsimport jsonfrom mitmproxy import ctxdef get_rpc(param):    url = "http://127.0.0.1:12080/go"    params = {        "group""zzz",        "action""encode",        "param": param.decode('utf-8', errors='ignore')    }    try:        result = requests.get(url, params=params, timeout=5)        # ctx.log.info(f"RPC Response: {result.text}")        # 第一次解析 JSON,获取外层结构        outer_data = result.json()        # 第二次解析 data 字段(字符串 -> 字典)        inner_data = json.loads(outer_data['data'])        return inner_data  # 直接返回解析后的内层数据    except Exception as e:        ctx.log.error(f"Error in get_rpc: {str(e)}")        return Nonedef get_responseRpc(param):    url = "http://127.0.0.1:12080/go"    params = {        "group""zzz",        "action""decode",        "param": param.decode('utf-8', errors='ignore')    }    try:        result = requests.get(url, params=params, timeout=5)        outer_data = result.json()        # 第二次解析 data 字段(字符串 -> 字典)        inner_data = json.loads(outer_data['data'])        return inner_data  # 直接返回解析后的内层数据    except Exception as e:        ctx.log.error(f"Error in get_rpc: {str(e)}")        return Nonedef request(flow):    original_body = flow.request.content    ctx.log.info(f"原始请求体: {original_body}")    result = get_rpc(original_body)    if result is None:        ctx.log.error("RPC failed, skipping request modification")        return    try:        # 直接使用内层数据        flow.request.headers['timestamp'] = result['time']        flow.request.headers['requestId'] = result['id']        flow.request.headers['sign'] = result['sign']        flow.request.content = result['request'].encode('utf-8')        flow.request.headers['Content-Length'] = str(len(flow.request.content))        ctx.log.info(f"加密后的请求体: {flow.request.content}")    except Exception as e:        ctx.log.error(f"Error in request: {str(e)}")def response(flow):    response_body = flow.response.content    ctx.log.info(f"响应体: {response_body}")    result = get_responseRpc(response_body)    if result is None:        ctx.log.error("Response RPC failed, keeping original response")        return    try:        # 将解码后的字典转为 JSON 字符串并编码为字节        decoded_json = json.dumps(result, ensure_ascii=False).encode('utf-8')        flow.response.content = decoded_json        flow.response.headers['Content-Length'] = str(len(flow.response.content))        # 可选:设置 Content-Type 为 JSON        flow.response.headers['Content-Type'] = 'application/json; charset=utf-8'        ctx.log.info(f"解码后的响应体: {flow.response.content}")    except Exception as e:        ctx.log.error(f"Error in response: {str(e)}")

然后设置burp的上游代理

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

运行脚本

mitmdump -p 8081 -s .JsPython.py 
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

这样即可实现自动化加解密

当密码不正确时

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

当密码正确时,这里请求头中的三个值在burp虽然没变但实际上是已经改变了的,因为是在脚本中做的处理

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

还是非常方便滴,因为不需要去逆js了,接下来是

JsRpc+Galaxy工具实现网站HTTP报文自动加解密+自动更新签名

Galaxy工具

可以做到在请求/响应在客户端/Burp/服务端流转时加入自己的处理逻辑,这可以用来实现请求/响应自动解密。

详情见https://github.com/outlaws-bai/Galaxy

JsRpc工具

在网站的控制台新建一个WebScoket客户端链接到服务器通信,调用服务器的接口 > 服务器会发送信息给客户端 > 客户端接收到要执行的方法执行完js代码后把获得想要的内容发回给服务器 > 服务器接收到后再显示出来。

详情见https://github.com/jxhczhl/JsRpc

环境靶场:

http://39.98.108.20:8085/

项目地址:

https://github.com/0ctDay/encrypt-decrypt-vuls/

JS逆向分析

网站数据包如下,数据进行加密处理,请求包的请求头内三个参数requestId、timestamp、sign缺一不可,改动任何一个都失效,且无法使用repeater重放数据

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

浏览器控制台定位相关js代码,其中关于请求头三个参数如下:

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

加密js代码如下,采用AES CBC key和iv都写在js内

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

JS内打上断点

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

可以看到其中n为需要传输的数据、timestamp通过Date.parse(new Date)获取、requestId通过函数p()获取、sign为a.a.MD5函数对传输的数据n加上timestamp加上requestId做MD5处理。l(n)为加密函数对传输的数据n进行加密。

控制台调用函数打印相关数据

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

注入JsRpc客户端及获取签名方法

在这里使用jsrpc调用接口执行js获取timestamp、requestId、sign三个请求头数据,而加密采用Galaxy自带加密模板。

jsrpc连接成功后,在浏览器控制台对相关函数进行注册

window.requestId=p//requestIdwindow.v1 = v//函数vwindow.sign=a.a.MD5//签名sign
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

连接通信

demo.regAction("hello",function (resolve,param) {    n=JSON.stringify(v1(param))    var time = Date.parse(new Date);    var id=requestId()    var sg = sign(n+id+time).toString()    var data={"time":"","id":"","sign":""}    data["time"]=time.toString()    data["id"]=id    data["sign"]=sg    resolve(data);})
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

这里可以直接通过浏览器访问查看对应结果

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

在Galaxy的hook脚本中调用JsRpc服务端

加解密

此处加密采用模板加解密python文件AES_CBC来实现

脚本内写入key、iv和对应算法

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

该网站内数据包采用GET和POST两种方式进行请求,且只有POST请求的数据进行加密处理,因此请求数据发送到burp解密和burp明文数据到服务器加密需要区分开

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)
JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

JsRpc引入

引入jsrpc需要jython引入http客户端

from org.m2sec.core.outer import HttpClient

按照格式构建引入jsrpc和替换请求头的代码

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)
burpRequestBody=request.getBody()            #获取传输数据,也就是上文中的nurl="http://127.0.0.1:12080/go?group=zzz&action=hello&param="jsrpcUrl=url+burpRequestBody                 #将n拼接urljsrpcRequest=request.of(jsrpcUrl)            #构建request请求jsrpcRespone=HttpClient.send(jsrpcRequest)   #发送数据包jsrpcResponeJson=jsrpcRespone.getJson()      #获取返回包内数据headData=jsrpcResponeJson["data"]            #提取data中内容headData=json.loads(headData)                #将JSON数据的字符串转换为Python中的数据类型time=headData["time"]                        #提取时间requestId=headData["id"]                     #提取requestIdsign=headData["sign"]                        #提取签名head=request.getHeaders()                    #提取原始数据包请求头head.put("sign",sign)                        #替换signhead.put("requestId",requestId)              #替换requestIdhead.put("timestamp",time)                   #替换时间request.setHeaders(head)                     #替换请求头

将构建好的代码写入到burp发送到服务器的函数zhong

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

效果图

自动加解密实现效果

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

重放数据实现效果

JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)

Galaxy完整的hook脚本

import jsonimport base64from org.m2sec.core.utils import (    CodeUtil,    CryptoUtil,    HashUtil,    JsonUtil,    MacUtil,    FactorUtil,)from org.m2sec.core.models import Request, Responsefrom org.m2sec.core.outer import HttpClientfrom java.lang import String"""内置示例,需要自定义代码文件时查看该文档:https://github.com/outlaws-bai/Galaxy/blob/main/docs/Custom.md按 Ctrl(control) + ` 可查看内置函数"""ALGORITHM = "AES/CBC/PKCS5Padding"secret = b"1234567891234567"iv = b"1234567891234567"paramMap = {"iv": iv}jsonKey = "data"log = Nonedef hook_request_to_burp(request):    """HTTP请求从客户端到达Burp时被调用。在此处完成请求解密的代码就可以在Burp中看到明文的请求报文。    Args:        request (Request): 请求对象    Returns:        Request: 经过处理后的request对象,返回null代表从当前节点开始流量不再需要处理    """    if(request.getMethod()=="GET"):        return request    else:    # 获取需要解密的数据       encryptedData = CodeUtil.b64decode(request.getBody())    # 调用内置函数解密       data = decrypt(encryptedData)    # 更新body为已加密的数据       request.setContent(data)       return requestdef hook_request_to_server(request):    """HTTP请求从Burp将要发送到Server时被调用。在此处完成请求加密的代码就可以将加密后的请求报文发送到Server。    Args:        request (Request): 请求对象    Returns:        Request: 经过处理后的request对象,返回null代表从当前节点开始流量不再需要处理    """    if(request.getMethod()=="GET"):        burpRequestBody=''        url="http://127.0.0.1:12080/go?group=zzz&action=hello&param="        jsrpcUrl=url+burpRequestBody        jsrpcRequest=request.of(jsrpcUrl)             jsrpcRespone=HttpClient.send(jsrpcRequest)        jsrpcResponeJson=jsrpcRespone.getJson()        headData=jsrpcResponeJson["data"]        headData=json.loads(headData)        time=headData["time"]        requestId=headData["id"]        sign=headData["sign"]        head=request.getHeaders()        head.put("sign",sign)        head.put("requestId",requestId)        head.put("timestamp",time)        request.setHeaders(head)        return request    # 获取被解密的数据    else:        data = request.getContent()        burpRequestBody=request.getBody()        url="http://127.0.0.1:12080/go?group=zzz&action=hello&param="        jsrpcUrl=url+burpRequestBody        jsrpcRequest=request.of(jsrpcUrl)             jsrpcRespone=HttpClient.send(jsrpcRequest)        jsrpcResponeJson=jsrpcRespone.getJson()        headData=jsrpcResponeJson["data"]        headData=json.loads(headData)        time=headData["time"]        requestId=headData["id"]        sign=headData["sign"]        head=request.getHeaders()        head.put("sign",sign)        head.put("requestId",requestId)        head.put("timestamp",time)        request.setHeaders(head)    # 调用内置函数加密回去        encryptedData = encrypt(data)    # 将已加密的数据转换为Server可识别的格式        body = CodeUtil.b64encode(encryptedData)    # 更新body        request.setContent(body)        log.info("header2: {}",request)        return requestdef hook_response_to_burp(response):    """HTTP请求从Server到达Burp时被调用。在此处完成响应解密的代码就可以在Burp中看到明文的响应报文。    Args:        response (Response): 响应对象    Returns:        Response: 经过处理后的response对象,返回null代表从当前节点开始流量不再需要处理    """    # 获取需要解密的数据    encryptedData = CodeUtil.b64decode(response.getBody())    # 调用内置函数解密    data = decrypt(encryptedData)    # 更新body    response.setContent(data)    return responsedef hook_response_to_client(response):    """HTTP请求从Burp将要发送到Client时被调用。在此处完成响应加密的代码就可以将加密后的响应报文返回给Client。    Args:        response (Response): 响应对象    Returns:        Response: 经过处理后的response对象,返回null代表从当前节点开始流量不再需要处理    """    # 获取被解密的数据    data = response.getContent()    # 调用内置函数加密回去    encryptedData = encrypt(data)    # 更新body    # 将已加密的数据转换为Server识别的格式    body = CodeUtil.b64encode(encryptedData)    # 更新body    response.setContent(body)    return responsedef decrypt(content):    return CryptoUtil.aesDecrypt(ALGORITHM, content, secret, paramMap)def encrypt(content):    return CryptoUtil.aesEncrypt(ALGORITHM, content, secret, paramMap)def set_log(log1):    """程序在最开始会自动调用该函数,在上方函数可以放心使用log对象"""    global log    log = log1

0x03 总结

通过JsRpc与Burp Suite(结合mitmproxy或Galaxy)的联动,无需深入逆向JS加密逻辑即可实现自动化加解密,大幅提升渗透测试效率。JsRpc负责调用客户端函数,Galaxy或mitmproxy处理加密/解密与签名更新,适用于复杂前端加密场景。喜欢的师傅可以点赞转发支持一下谢谢!
0x04

原文始发于微信公众号(渗透安全HackTwo):JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)|挖洞技巧

 

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月26日00:41:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JsRpc与Burp Suite联动 自动化加解密的完整实战指南(详细版)https://cn-sec.com/archives/4168911.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息