跳转至

Burp联动其他工具

xray基础配置

xray配置文件为同目录下的config.yaml

YAML
version: 4.0

parallel: 30                      # 漏洞探测的 worker 数量,可以简单理解为同时有 30 个 POC 在运行

# 全局 http 发包配置
# 更多解释见 https://docs.xray.cool/#/configration/http
http:
  proxy: ""                             # 漏洞扫描时使用的代理,如: http://127.0.0.1:8080。 如需设置多个代理,请使用 proxy_rule 或自行创建上层代理
  proxy_rule: []                        # 漏洞扫描使用多个代理的配置规则, 具体请参照文档
  dial_timeout: 5                       # 建立 tcp 连接的超时时间
  read_timeout: 10                      # 读取 http 响应的超时时间,不可太小,否则会影响到 sql 时间盲注的判断
  max_conns_per_host: 50                # 同一 host 最大允许的连接数,可以根据目标主机性能适当增大
  enable_http2: false                   # 是否启用 http2, 开启可以提升部分网站的速度,但目前不稳定有崩溃的风险
  fail_retries: 0                       # 请求失败的重试次数,0 则不重试
  max_redirect: 5                       # 单个请求最大允许的跳转数
  max_resp_body_size: 2097152           # 最大允许的响应大小, 默认 2M
  max_qps: 500                          # 每秒最大请求数
  allow_methods:                        # 允许的请求方法
  - HEAD
  - GET
  - POST
  - PUT
  - PATCH
  - DELETE
  - OPTIONS
  - CONNECT
  - TRACE
  - MOVE
  - PROPFIND
  headers:
    User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0
    # Cookie: key=value

# 漏洞探测的插件配置
# 更多解释见 https://docs.xray.cool/#/configration/plugins
plugins:
  baseline:
    enabled: true
    detect_cors_header_config: true     # 检查 cors 相关配置
    detect_server_error_page: true      # 检查服务器错误信息
    detect_phpinfo: true                # 检查响应是否包含phpinfo
    detect_system_path_leak: true      # 检查响应是否包含系统路径泄露
    detect_outdated_ssl_version: false  # 检查 ssl 版本问题
    detect_http_header_config: false    # 检查 http 安全相关 header 是否配置
    detect_cookie_httponly: true       # 检查 set-cookie 时是否设置 http only
    detect_china_id_card_number: false  # 检查响应是否存在身份证号
    detect_china_phone_number: false    # 检查响应是否存在电话号码
    detect_china_bank_card: false       # 检查响应是否存在银行卡号
    detect_private_ip: false            # 检查响应是否包含内网 ip
  brute-force:
    enabled: true
    username_dictionary: ""             # 自定义用户名字典, 为空将使用内置 TOP10, 配置后将与内置字典**合并**
    password_dictionary: ""             # 自定义密码字典,为空将使用内置 TOP100, 配置后将与内置字典**合并**
  cmd-injection:
    enabled: true
  crlf-injection:
    enabled: true
  dirscan:
    enabled: true
    depth: 1                            # 检测深度,定义 http://t.com/a/ 深度为 1, http://t.com/a 深度为 0
    dictionary: ""                      # 自定义检测字典, 配置后将与内置字典**合并**
    exclude_dir: []                     # 想要排除的内部的扫描category,例如["sensitive/crossdomain","system/key"]
  fastjson:
    enabled: true
  jsonp:
    enabled: true
  path-traversal:
    enabled: true
  phantasm:                             # poc 插件
    enabled: true
    depth: 1
    auto_load_poc: false                # 除内置 poc 外,额外自动加载当前目录以 "poc-" 为文件名前缀的POC文件,等同于在 include_poc 中增加 "./poc-*"
    exclude_poc: []                     # 排除哪些 poc, 支持 glob 语法, 如: "/home/poc/*thinkphp*" 或 "poc-yaml-weblogic*"
    include_poc: [./xray_pocs/*]                     # 只使用哪些内置 poc 以及 额外加载哪些本地 poc, 支持 glob 语法, 如:"*weblogic*" 或 "/home/poc/*"
                                        # 也可使用 --poc 仅运行 指定的内置或本地 poc,进行测试。
                                        # 例如,可使用如下命令,仅运行当前目录下的 poc 且 不运行内置 poc 进行测试:
                                        # webscan -poc ./poc-* -url http://example.com
    poc_tags:                           # 为POC添加tag, 然后就可以使用--tags来选择启动哪些POC。poc-yaml-test为poc的name,[]中的内容为该POC对应的标签
      poc-yaml-test: ["HW", "ST"]
      poc-yaml-test-1: ["ST"]                       
  redirect:
    enabled: true
  shiro:
    enabled: true
    cookie_name: rememberMe             # 默认使用哪个 shiro cookie name
    aes_key: []                         # 自定义 shiro key,配置后将与内置 116 key 做合并
    aes_key_file:                       # 自定义存储 shiro key 的文件路径,配置后将自动加载文件中的key
  sqldet:
    enabled: true
    boolean_based_detection: true       # 是否检测布尔盲注
    error_based_detection: true         # 是否检测报错注入
    time_based_detection: true          # 是否检测时间盲注
    use_comment_in_payload: false       # 是否在时间盲注中使用 comment 关键字, 有风险, 建议不开
    detect_sqli_in_cookie: true         # 是否检查在 cookie 中的注入
  ssrf:
    enabled: true
  struts:
    enabled: true
  thinkphp:
    enabled: true
    detect_thinkphp_sqli: true          # 检查 thinkphp 特定语法的 sqli 注入漏洞
  upload:
    enabled: true
  xss:
    enabled: true
    detect_xss_in_cookie: true          # 是否探测入口点在 cookie 中的 xss
    ie_feature: false                   # 是否扫描仅能在 ie 下利用的 xss
  xxe:
    enabled: true
  xstream:
    enabled: true
    full: false                         # 是否完全扫描,一般情况下只通过post请求body发post
                                        # 如果开启完全扫描,则会有大量请求对每一个参数进行测试

# 反连平台配置,更多解释见 https://docs.xray.cool/#/configration/reverse
# 注意: 默认配置为禁用反连平台,这是无法扫描出依赖反连平台的漏洞,这些漏洞包括 fastjson,ssrf 以及 poc 中依赖反连的情况等
reverse:
  db_file_path: ""                      # 反连平台数据库文件位置, 这是一个 KV 数据库
  token: ""                             # 反连平台认证的 Token, 独立部署时不能为空
  http:
    enabled: false
    listen_ip: 0.0.0.0 
    listen_port: ""
    ip_header: ""                       # 在哪个 http header 中取 ip,为空代表从 REMOTE_ADDR 中取
  dns:
    enabled: false
    listen_ip: 0.0.0.0 
    domain: ""                          # DNS 域名配置
    is_domain_name_server: false        # 是否修改了域名的 ns 为反连平台,如果是,那 nslookup 等就不需要指定 dns 了
    resolve:                            # DNS 静态解析规则
    - type: A                           # A, AAAA, TXT 三种
      record: localhost
      value: 127.0.0.1
      ttl: 60
  client:
    remote_server: false                # 是否是独立的远程 server,如果是要在下面配置好远程的服务端地址
    http_base_url: ""                   # 默认将根据 ListenIP 和 ListenPort 生成,该地址是存在漏洞的目标反连回来的地址, 当反连平台前面有反代、绑定域名、端口映射时需要自行配置
    dns_server_ip: ""                   # 和 http_base_url 类似,实际用来访问 dns 服务器的地址

# 被动代理配置
# 更多解释见 https://docs.xray.cool/#/configration/mitm
mitm:
  ca_cert: ./ca.crt                     # CA 根证书路径
  ca_key: ./ca.key                      # CA 私钥路径
  basic_auth:                           # 基础认证的用户名密码
    username: ""
    password: ""
  allow_ip_range: []                    # 允许的 ip,可以是 ip 或者 cidr 字符串
  restriction:                          # 代理能够访问的资源限制, 以下各项为空表示不限制
    hostname_allowed: []                # 允许访问的 Hostname,支持格式如 t.com、*.t.com、1.1.1.1、1.1.1.1/24、1.1-4.1.1-8
    hostname_disallowed:                # 不允许访问的 Hostname,支持格式如 t.com、*.t.com、1.1.1.1、1.1.1.1/24、1.1-4.1.1-8
    - '*google*'
    - '*github*'
    - '*.gov.cn'
    - '*.edu.cn'
    - '*chaitin*'
    - '*.xray.cool'
    port_allowed: []                    # 允许访问的端口, 支持的格式如: 80、80-85
    port_disallowed: []                 # 不允许访问的端口, 支持的格式如: 80、80-85
    path_allowed: []                    # 允许访问的路径,支持的格式如: test、*test*
    path_disallowed: []                 # 不允许访问的路径, 支持的格式如: test、*test*
    query_key_allowed: []               # 允许访问的 Query Key,支持的格式如: test、*test*
    query_key_disallowed: []            # 不允许访问的 Query Key, 支持的格式如: test、*test*
    fragment_allowed: []                # 允许访问的 Fragment, 支持的格式如: test、*test*
    fragment_disallowed: []             # 不允许访问的 Fragment, 支持的格式如: test、*test*
    post_key_allowed: []                # 允许访问的 Post Body 中的参数, 支持的格式如: test、*test*
    post_key_disallowed: []             # 不允许访问的 Post Body 中的参数, 支持的格式如: test、*test*
  queue:
    max_length: 3000                    # 队列长度限制, 也可以理解为最大允许多少等待扫描的请求, 请根据内存大小自行调整
  proxy_header:
    via: ""                             # 是否为代理自动添加 Via 头
    x_forwarded: false                  # 是否为代理自动添加 X-Forwarded-{For,Host,Proto,Url} 四个 http 头
  upstream_proxy: "http://127.0.0.1:2453"                    # 为 mitm 本身配置独立的代理

# 基础爬虫配置
# 更多解释见 https://docs.xray.cool/#/configration/basic-crawler
basic-crawler:
  max_depth: 0                          # 最大爬取深度, 0 为无限制
  max_count_of_links: 0                 # 本次爬取收集的最大链接数, 0 为无限制
  allow_visit_parent_path: false        # 是否允许爬取父目录, 如果扫描目标为 t.com/a/且该项为 false, 那么就不会爬取 t.com/ 这级的内容
  restriction:                          # 爬虫的允许爬取的资源限制, 为空表示不限制。爬虫会自动添加扫描目标到 Hostname_allowed。
    hostname_allowed: []                # 允许访问的 Hostname,支持格式如 t.com、*.t.com、1.1.1.1、1.1.1.1/24、1.1-4.1.1-8
    hostname_disallowed:                # 不允许访问的 Hostname,支持格式如 t.com、*.t.com、1.1.1.1、1.1.1.1/24、1.1-4.1.1-8
    - '*google*'
    - '*github*'
    - '*.gov.cn'
    - '*.edu.cn'
    - '*chaitin*'
    - '*.xray.cool'
    port_allowed: []                    # 允许访问的端口, 支持的格式如: 80、80-85
    port_disallowed: []                 # 不允许访问的端口, 支持的格式如: 80、80-85
    path_allowed: []                    # 允许访问的路径,支持的格式如: test、*test*
    path_disallowed: []                 # 不允许访问的路径, 支持的格式如: test、*test*
    query_key_allowed: []               # 允许访问的 Query Key,支持的格式如: test、*test*
    query_key_disallowed: []            # 不允许访问的 Query Key, 支持的格式如: test、*test*
    fragment_allowed: []                # 允许访问的 Fragment, 支持的格式如: test、*test*
    fragment_disallowed: []             # 不允许访问的 Fragment, 支持的格式如: test、*test*
    post_key_allowed: []                # 允许访问的 Post Body 中的参数, 支持的格式如: test、*test*
    post_key_disallowed: []             # 不允许访问的 Post Body 中的参数, 支持的格式如: test、*test*
  basic_auth:                           # 基础认证信息
    username: ""
    password: ""

# 子域名扫描配置,配置解释见 https://docs.xray.cool/#/configration/subdomain
# 注意:该功能仅限高级版用户使用
subdomain:
  max_parallel: 500                     # 子域名探测的并发度
  allow_recursion: false                # 是否允许递归探测, 开启后,扫描完一级域名后,会自动将一级的每个域名作为新的目标
  max_recursion_depth: 3                # 最大允许的递归深度, 3 表示 3 级子域名 仅当 allow_recursion 开启时才有意义
  web_only: false                       # 结果中仅显示有 web 应用的, 没有 web 应用的将被丢弃
  ip_only: false                        # 结果中仅展示解析出 IP 的,没有解析成功的将被丢弃
  servers:                              # 子域名扫描过程中使用的 DNS Server
  - 8.8.8.8
  - 8.8.4.4
  - 223.5.5.5
  - 223.6.6.6
  - 114.114.114.114
  sources:
    brute:
      enabled: true
      main_dict: ""                     # 一级大字典路径,为空将使用内置的 TOP 30000 字典
      sub_dict: ""                      # 其他级小字典路径,为空将使用内置过的 TOP 100 字典
    httpfinder:
      enabled: true                     # 使用 http 的一些方式来抓取子域名,包括 js, 配置文件,http header 等等
    dnsfinder:
      enabled: true                     # 使用 dns 的一些错误配置来找寻子域名,如区域传送(zone transfer)
    certspotter:                        # 下面的通过 api 获取的了
      enabled: true
    crt:
      enabled: true
    hackertarget:
      enabled: true
    qianxun:
      enabled: true
    rapiddns:
      enabled: true
    sublist3r:
      enabled: true
    threatminer:
      enabled: true
    virusTotal:
      enabled: true
    alienvault:
      enabled: true
    bufferover:
      enabled: true
    fofa:
      enabled: false
      email: ""
      key: ""
    ip138:
      enabled: true
    myssl:
      enabled: true
    riskiq:
      enabled: false
      user: ""
      key: ""
    quake:
      enabled: false
      key: ""
    baidu:
      enabled: true
      page_limit: 12
    yahoo:
      enabled: true
      page_limit: 12
    sogou:
      enabled: true
      page_limit: 12
    google:
      enabled: true
      page_limit: 12
    bing:
      enabled: true
      page_limit: 12
    ask:
      enabled: true
      page_limit: 12

可根据个人需求配置

burp&xray

在burp → settings → Network → Connections找到上游代理设置

在点击Add弹出来的窗口中

  • 第一项Destination host为走代理的主机地址,我们可以直接用通配符*****来指定所有目的主机。
  • 第二项为代理的ip地址,如果是本地程序,填写回环地址127.0.0.1即可,如果是远程的代理服务器,根据实际情况填写即可。
  • 第三项为代理的端口,这里的端口填写在“前期操作”中软件或者服务器开放的端口

若上游代理软件**没有特殊设置**(例如需用户名和密码连接),下面的第四项保持None选项即可,剩下的空着即可

Text Only
*
127.0.0.1 (VPS_IP)
7777 (PORT)

xray启动:

Bash
./xray webscan --listen 127.0.0.1:7777 --html-output xxx_scan.html

可以看到已经成功联动,此时流量流动方向为:burp → yakit

burp&yakit

yakit代理地址为127.0.0.1:8083,配置burp的上游代理为yakit代理地址

可以看到yakit抓取到流量,此时流量流动方向为:burp → yakit

burp&yakit&xray

  • xray
Bash
./xray webscan --listen 127.0.0.1:7777 --html-output xxx_scan.html
  • yakit

选择下游代理为xray监听地址

  • burp

配置上游地址为yakit监听地址

可以看到三个工具都能抓到流量,此时流量流动方向为:burp → yakit → xray

burp&appscan&xray

  • appscan

在options中配置监听端口

  • xray

编辑xray目录下的config.yaml,该配置文件在初次使用xray后会自动生成

YAML
# 配置为appscan监听地址
upstream_proxy: "http://127.0.0.1:2453"

随后启动xray监听

Bash
./xray webscan --listen 127.0.0.1:3333 --html-output xxx_scan.html
  • burp

配置为xray监听地址127.0.0.1:3333

可以看到三个工具都能抓到流量,此时流量流动方向为burp → xray → appscan

burp&JsRpc&MitmProxy

请求响应AES加密

  • server
Python
from flask import Flask, request
from flask_cors import CORS  # type: ignore
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import json

app = Flask(__name__)
CORS(app)  # Enable CORS for all routes

# AES key and IV (must be the same on both client and server)
AES_KEY = b'1234567890123456'  # 16 bytes key
AES_IV = b'1234567890123456'   # 16 bytes IV


# Helper functions for AES encryption and decryption
def aes_encrypt(plaintext):
    cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
    padded = pad(plaintext.encode('utf-8'), AES.block_size)
    encrypted = cipher.encrypt(padded)
    return base64.b64encode(encrypted).decode('utf-8')


def aes_decrypt(ciphertext):
    cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
    decrypted = cipher.decrypt(base64.b64decode(ciphertext))
    return unpad(decrypted, AES.block_size).decode('utf-8')


# Dummy user database
USER_DB = {
    "testuser": "password123",
    "admin": "adminpass"
}


@app.route('/login', methods=['POST'])
def login():
    try:
        # Decrypt the incoming request body
        encrypted_data = request.data.decode('utf-8')
        decrypted_data = aes_decrypt(encrypted_data)
        credentials = json.loads(decrypted_data)

        username = credentials.get('username')
        password = credentials.get('password')

        # Validate username and password
        if username in USER_DB and USER_DB[username] == password:
            response = {"status": "success", "message": "Login successful"}
        else:
            response = {"status": "failure",
                        "message": "Invalid username or password"}

        # Encrypt the response
        encrypted_response = aes_encrypt(json.dumps(response))
        return encrypted_response

    except Exception as e:
        error_response = {"status": "error", "message": str(e)}
        encrypted_error_response = aes_encrypt(json.dumps(error_response))
        return encrypted_error_response


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)
  • client
HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Client Test</title>
    <script src="https://gcore.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.min.js"></script>
</head>
<body>
    <h1>Login</h1>
    <form id="loginForm">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required>
        <br><br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required>
        <br><br>
        <button type="submit">Login</button>
    </form>
    <p id="response"></p>

    <script>
        // AES key and IV (must match the server)
        const AES_KEY = CryptoJS.enc.Utf8.parse('1234567890123456'); // 16 bytes key
        const AES_IV = CryptoJS.enc.Utf8.parse('1234567890123456');  // 16 bytes IV

        // Helper function for AES encryption
        function aesEncrypt(plaintext) {
            const encrypted = CryptoJS.AES.encrypt(plaintext, AES_KEY, {
                iv: AES_IV,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            });
            return encrypted.toString();
        }

        // Helper function for AES decryption
        function aesDecrypt(ciphertext) {
            const decrypted = CryptoJS.AES.decrypt(ciphertext, AES_KEY, {
                iv: AES_IV,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            });
            return decrypted.toString(CryptoJS.enc.Utf8);
        }

        // Handle form submission
        document.getElementById('loginForm').addEventListener('submit', async function(event) {
            event.preventDefault();

            const username = document.getElementById('username').value;
            const password = document.getElementById('password').value;

            // Prepare the credentials
            const credentials = JSON.stringify({ username, password });

            // Encrypt the credentials
            const encryptedData = aesEncrypt(credentials);

            try {
                // Send the POST request
                const response = await fetch('http://192.168.1.102:8080/login', {
                    method: 'POST',
                    headers: { 'Content-Type': 'text/plain' },
                    body: encryptedData
                });

                // Read and decrypt the server response
                const encryptedResponse = await response.text();
                const decryptedResponse = aesDecrypt(encryptedResponse);

                // Display the response
                document.getElementById('response').textContent = decryptedResponse;
            } catch (error) {
                document.getElementById('response').textContent = 'Error: ' + error.message;
            }
        });
    </script>
</body>
</html>

image-20250505110758141

bp抓包发现请求和响应都被加密了

寻找加解密逻辑

image-20250505111151820

通过调试和查看前端代码可以发现:

  • 请求加密逻辑调用了aesEncrypt函数,参数为json后的username和password
  • 响应解密逻辑调用了aesDecrypt函数,参数为服务端返回的响应

JsRpc启动和客户端注入

找到加密/解密函数后,我们启动jsrpc服务端

Bash
go run main.go
# 也可以下载项目编译好的可执行文件执行

image-20250505112121021

客户端在控制台注入JsEnv_Dev.js文件

JavaScript
var rpc_client_id, Hlclient = function (wsURL) {
    this.wsURL = wsURL;
    this.handlers = {
        _execjs: function (resolve, param) {
            var res = eval(param)
            if (!res) {
                resolve("没有返回值")
            } else {
                resolve(res)
            }
        }
    };
    this.socket = undefined;
    if (!wsURL) {
        throw new Error('wsURL can not be empty!!')
    }
    this.connect()
}
Hlclient.prototype.connect = function () {
    if (this.wsURL.indexOf("clientId=") === -1 && rpc_client_id) {
        this.wsURL += "&clientId=" + rpc_client_id
    }
    console.log('begin of connect to wsURL: ' + this.wsURL);
    var _this = this;
    try {
        this.socket = new WebSocket(this.wsURL);
        this.socket.onmessage = function (e) {
            _this.handlerRequest(e.data)
        }
    } catch (e) {
        console.log("connection failed,reconnect after 10s");
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket.onclose = function () {
        console.log('rpc已关闭');
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket.addEventListener('open', (event) => {
        console.log("rpc连接成功");
    });
    this.socket.addEventListener('error', (event) => {
        console.error('rpc连接出错,请检查是否打开服务端:', event.error);
    })
};
Hlclient.prototype.send = function (msg) {
    this.socket.send(msg)
}
Hlclient.prototype.regAction = function (func_name, func) {
    if (typeof func_name !== 'string') {
        throw new Error("an func_name must be string");
    }
    if (typeof func !== 'function') {
        throw new Error("must be function");
    }
    console.log("register func_name: " + func_name);
    this.handlers[func_name] = func;
    return true
}
Hlclient.prototype.handlerRequest = function (requestJson) {
    var _this = this;
    try {
        var result = JSON.parse(requestJson)
    } catch (error) {
        console.log("请求信息解析错误", requestJson);
        return
    }
    if (result["registerId"]) {
        rpc_client_id = result['registerId']
        return
    }
    if (!result['action'] || !result["message_id"]) {
        console.warn('没有方法或者消息id,不处理');
        return
    }
    var action = result["action"], message_id = result["message_id"]
    var theHandler = this.handlers[action];
    if (!theHandler) {
        this.sendResult(action, message_id, 'action没找到');
        return
    }
    try {
        if (!result["param"]) {
            theHandler(function (response) {
                _this.sendResult(action, message_id, response);
            })
            return
        }
        var param = result["param"]
        try {
            param = JSON.parse(param)
        } catch (e) {
        }
        theHandler(function (response) {
            _this.sendResult(action, message_id, response);
        }, param)
    } catch (e) {
        console.log("error: " + e);
        _this.sendResult(action, message_id, e);
    }
}
Hlclient.prototype.sendResult = function (action, message_id, e) {
    if (typeof e === 'object' && e !== null) {
        try {
            e = JSON.stringify(e)
        } catch (v) {
            console.log(v)//不是json无需操作
        }
    }
    this.send(JSON.stringify({"action": action, "message_id": message_id, "response_data": e}));
}

客户端控制台连接服务端

JavaScript
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");

image-20250505112426481

注册全局函数

我们的关注点在请求的加解密上

注册解密方法
JavaScript
// 注册参数函数
window.json_parms = function(){
  // 复制前端相关代码即可
  const username = document.getElementById('username').value;
  const password = document.getElementById('password').value;

  // Prepare the credentials
  const credentials = JSON.stringify({ username, password });
  return credentials;
};

// 注册请求加密全局函数
window.enc_request = function(data){
  return aesEncrypt(data);
};
// 返回找到的对应加密函数结果

注册加密方法

JavaScript
// 注册函数
demo.regAction("req", function(resolve) {
    // 加密请求体
    let encstr = window.enc_request(window.json_parms());
    let res = {
        "encstr": encstr,
    };
    resolve(res);
});

image-20250505115028528

注册解密方法

调用加密函数测试结果正确,接下来注册解密函数

JavaScript
// 注册响应全局解密函数
window.dec_response = function(data){
  return aesDecrypt(data);
};
// 返回找到的对应解密函数结果

注册解密方法

JavaScript
// 注册函数
demo.regAction("res", function(resolve, param) {
    // 解密响应体
    let decstr = window.dec_response(param);
    let res = {
        "decstr": decstr,
    };
    resolve(res);
});

image-20250505115659269

调用解密函数测试结果正确

接口测试

Text Only
# 加密测试
http://127.0.0.1:12080/go?group=zzz&action=req

# 解密测试
http://127.0.0.1:12080/go?group=zzz&action=res&param="MTQ129pr5j4oWbouS07UszP5SbGAI+60k0htm0Pfzvd+N/afHRuTdHSd0J8qd4f00kfSUNiGHjI+3JNXZ/lcKgsxdoQBlRh9PX2LaNg+2X0="

image-20250505122056924

image-20250505121943786

需要注意的是,由于aesDecrypt参数是从响应体中获取的,所以需要POST请求

编写mitmproxy脚本