JsRpc+Galaxy 实现网站HTTP报文自动加解密+自动更新签名
字数 1759 2025-08-22 22:47:30

JsRpc+Galaxy 实现网站HTTP报文自动加解密与签名更新技术指南

一、技术背景与工具简介

1.1 技术背景

现代Web应用常对HTTP请求/响应进行加密处理,并添加签名验证机制,这给安全测试带来挑战:

  • 请求/响应数据加密,BurpSuite无法直接查看明文
  • 签名机制导致无法直接重放请求
  • 手动解密/加密效率低下

1.2 工具组合

Galaxy

  • BurpSuite插件,可在请求/响应流转过程中插入自定义处理逻辑
  • 支持请求/响应自动加解密
  • GitHub: https://github.com/outlaws-bai/Galaxy

JsRpc

  • 通过WebSocket与浏览器客户端通信
  • 可直接调用浏览器中的JavaScript函数
  • 避免逆向复杂的加密逻辑
  • GitHub: https://github.com/jxhczhl/JsRpc

二、环境准备

2.1 测试环境

  • 靶场地址: http://39.98.108.20:8085/
  • 加密特征:
    • 请求头包含三个关键参数:requestId、timestamp、sign
    • POST请求体使用AES CBC模式加密
    • 签名机制:MD5(请求数据 + timestamp + requestId)

2.2 工具安装

  1. 安装BurpSuite
  2. 安装Galaxy插件
  3. 部署JsRpc服务端
  4. 在目标网站注入JsRpc客户端脚本

三、技术实现步骤

3.1 JS逆向分析

  1. 定位加密相关JavaScript代码:

    • requestId由函数p()生成
    • timestamp通过Date.parse(new Date)获取
    • sign使用a.a.MD5函数处理
    • 数据加密使用l(n)函数(AES CBC)
  2. 关键加密参数:

    key = "1234567891234567"
    iv = "1234567891234567"
    

3.2 JsRpc客户端注入

  1. 在浏览器控制台注册关键函数:

    window.requestId = p;  // requestId生成函数
    window.v1 = v;        // 数据处理函数
    window.sign = a.a.MD5; // 签名函数
    
  2. 注册JsRpc调用接口:

    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);
    });
    

3.3 Galaxy配置与脚本编写

3.3.1 基础配置

ALGORITHM = "AES/CBC/PKCS5Padding"
secret = b"1234567891234567"
iv = b"1234567891234567"
paramMap = {"iv": iv}
jsonKey = "data"

3.3.2 关键Hook函数

  1. 请求到达Burp时解密 (hook_request_to_burp):

    def hook_request_to_burp(request):
        if (request.getMethod() == "GET"):
            return request
        else:
            encryptedData = CodeUtil.b64decode(request.getBody())
            data = decrypt(encryptedData)
            request.setContent(data)
            return request
    
  2. 请求发送到服务器前加密 (hook_request_to_server):

    def hook_request_to_server(request):
        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)
            body = CodeUtil.b64encode(encryptedData)
            request.setContent(body)
            log.info("header2: {}", request)
            return request
    
  3. 响应到达Burp时解密 (hook_response_to_burp):

    def hook_response_to_burp(response):
        encryptedData = CodeUtil.b64decode(response.getBody())
        data = decrypt(encryptedData)
        response.setContent(data)
        return response
    
  4. 响应返回客户端前加密 (hook_response_to_client):

    def hook_response_to_client(response):
        data = response.getContent()
        encryptedData = encrypt(data)
        body = CodeUtil.b64encode(encryptedData)
        response.setContent(body)
        return response
    

3.4 加解密函数

def decrypt(content):
    return CryptoUtil.aesDecrypt(ALGORITHM, content, secret, paramMap)

def encrypt(content):
    return CryptoUtil.aesEncrypt(ALGORITHM, content, secret, paramMap)

四、技术实现原理

4.1 工作流程

  1. 请求流程

    • 客户端发送加密请求 → Burp(Galaxy解密) → 测试人员查看明文
    • 测试人员修改请求 → Galaxy调用JsRpc获取新签名 → Galaxy加密请求 → 发送到服务器
  2. 响应流程

    • 服务器返回加密响应 → Burp(Galaxy解密) → 测试人员查看明文
    • 测试人员修改响应 → Galaxy加密响应 → 返回给客户端

4.2 关键技术点

  1. 签名自动更新

    • 通过JsRpc调用浏览器中的原始签名函数
    • 确保每次请求的签名有效
  2. 加解密处理

    • Galaxy使用与客户端相同的加密算法和密钥
    • 自动识别GET/POST请求差异处理
  3. 请求头更新

    • 自动更新timestamp、requestId和sign
    • 保持请求头与签名的一致性

五、注意事项与优化建议

  1. 性能考虑

    • JsRpc调用会增加请求处理时间
    • 可缓存短时间内有效的签名
  2. 错误处理

    • 添加JsRpc调用失败的回退机制
    • 记录加解密失败日志
  3. 扩展性

    • 可支持多种加密算法
    • 可配置不同API的签名规则
  4. 安全考虑

    • 保护JsRpc服务端,防止未授权访问
    • 加密密钥应妥善保管

六、完整脚本示例

参见原文提供的完整Galaxy hook脚本,包含所有必要函数和导入声明。

七、参考资料

  1. Galaxy文档: https://github.com/outlaws-bai/Galaxy/blob/main/docs/Custom.md
  2. JsRpc项目: https://github.com/jxhczhl/JsRpc
  3. Galaxy基础教程: https://xz.aliyun.com/t/15051

通过本方案,安全测试人员可以高效处理加密API的测试工作,无需手动解密/加密或担心签名失效问题,大幅提升测试效率。

JsRpc+Galaxy 实现网站HTTP报文自动加解密与签名更新技术指南 一、技术背景与工具简介 1.1 技术背景 现代Web应用常对HTTP请求/响应进行加密处理,并添加签名验证机制,这给安全测试带来挑战: 请求/响应数据加密,BurpSuite无法直接查看明文 签名机制导致无法直接重放请求 手动解密/加密效率低下 1.2 工具组合 Galaxy : BurpSuite插件,可在请求/响应流转过程中插入自定义处理逻辑 支持请求/响应自动加解密 GitHub: https://github.com/outlaws-bai/Galaxy JsRpc : 通过WebSocket与浏览器客户端通信 可直接调用浏览器中的JavaScript函数 避免逆向复杂的加密逻辑 GitHub: https://github.com/jxhczhl/JsRpc 二、环境准备 2.1 测试环境 靶场地址: http://39.98.108.20:8085/ 加密特征: 请求头包含三个关键参数:requestId、timestamp、sign POST请求体使用AES CBC模式加密 签名机制:MD5(请求数据 + timestamp + requestId) 2.2 工具安装 安装BurpSuite 安装Galaxy插件 部署JsRpc服务端 在目标网站注入JsRpc客户端脚本 三、技术实现步骤 3.1 JS逆向分析 定位加密相关JavaScript代码: requestId 由函数 p() 生成 timestamp 通过 Date.parse(new Date) 获取 sign 使用 a.a.MD5 函数处理 数据加密使用 l(n) 函数(AES CBC) 关键加密参数: 3.2 JsRpc客户端注入 在浏览器控制台注册关键函数: 注册JsRpc调用接口: 3.3 Galaxy配置与脚本编写 3.3.1 基础配置 3.3.2 关键Hook函数 请求到达Burp时解密 ( hook_request_to_burp ): 请求发送到服务器前加密 ( hook_request_to_server ): 响应到达Burp时解密 ( hook_response_to_burp ): 响应返回客户端前加密 ( hook_response_to_client ): 3.4 加解密函数 四、技术实现原理 4.1 工作流程 请求流程 : 客户端发送加密请求 → Burp(Galaxy解密) → 测试人员查看明文 测试人员修改请求 → Galaxy调用JsRpc获取新签名 → Galaxy加密请求 → 发送到服务器 响应流程 : 服务器返回加密响应 → Burp(Galaxy解密) → 测试人员查看明文 测试人员修改响应 → Galaxy加密响应 → 返回给客户端 4.2 关键技术点 签名自动更新 : 通过JsRpc调用浏览器中的原始签名函数 确保每次请求的签名有效 加解密处理 : Galaxy使用与客户端相同的加密算法和密钥 自动识别GET/POST请求差异处理 请求头更新 : 自动更新timestamp、requestId和sign 保持请求头与签名的一致性 五、注意事项与优化建议 性能考虑 : JsRpc调用会增加请求处理时间 可缓存短时间内有效的签名 错误处理 : 添加JsRpc调用失败的回退机制 记录加解密失败日志 扩展性 : 可支持多种加密算法 可配置不同API的签名规则 安全考虑 : 保护JsRpc服务端,防止未授权访问 加密密钥应妥善保管 六、完整脚本示例 参见原文提供的完整Galaxy hook脚本,包含所有必要函数和导入声明。 七、参考资料 Galaxy文档: https://github.com/outlaws-bai/Galaxy/blob/main/docs/Custom.md JsRpc项目: https://github.com/jxhczhl/JsRpc Galaxy基础教程: https://xz.aliyun.com/t/15051 通过本方案,安全测试人员可以高效处理加密API的测试工作,无需手动解密/加密或担心签名失效问题,大幅提升测试效率。