笔者在进行api接口的测试时(因为菜没有工具,只能另辟蹊跷),使用postman+xray进行安全测试,但是因为nonce参数检测的缘故,导致xray的发出的扫描包全部失效,导致无法使用xray进行安全扫描,由此引入问题。

这种方式,流量走向还是 postman --> xray --> 服务器
查看xray的配置文件,我的版本为1.9,配置文件config.yaml

但是在这个配置文件中,headers的配置的值是静态的,nonce的值并不能动态变化,也就是说每次发包的nonce值还是一致的,并没有解决问题。此条思路pass,或者是我理解的不够,没有配置好,希望知道的大佬告知一声。
后来决定另辟一条线,就是给xray加代理,在xray的上层代理处将xray发出扫描的扫描请求包的header头中nonce替换掉,已实现绕过api防止重放的验证。

在xray的配置文件中配置代理即可,当前xray支持 https http socket5的代理


我这里为了实现上述的解决方案,用了postman+xray+burpsuite的结局方案。
整理思路及配置如下:

双击对应的证书文件即可



# -*- coding: utf-8 -*- from burp import IBurpExtender from burp import IHttpListener import random import string class BurpExtender(IBurpExtender, IHttpListener): def registerExtenderCallbacks(self, callbacks): # 获取 Burp 的回调对象 self._callbacks = callbacks # 获取扩展工具 self._helpers = callbacks.getHelpers() # 设置扩展名 callbacks.setExtensionName("Nonce Modifier") # 注册 HTTP 监听器 callbacks.registerHttpListener(self) def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # 仅处理请求 if messageIsRequest: print("Processing HTTP request message") # 获取请求信息 request_info = self._helpers.analyzeRequest(messageInfo.getRequest()) headers = request_info.getHeaders() # 修改请求头中的 nonce 参数 modified_headers = self.modifyNonceHeader(headers) # 打印修改后的请求头 print("Modified Headers:", modified_headers) # 构造修改后的请求 modified_request = self._helpers.buildHttpMessage(modified_headers, messageInfo.getRequest()[request_info.getBodyOffset():]) # 更新请求消息 messageInfo.setRequest(modified_request) def modifyNonceHeader(self, headers): # 寻找并修改 nonce 参数 for i in range(len(headers)): if headers[i].lower().startswith("nonce:"): headers[i] = "Nonce: {}".format(self.generateRandomNonce()) return headers def generateRandomNonce(self): # 生成随机 8 位字符串 # 生成随机 8 位字符串,并去除两侧空白字符 nonce = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(8)).strip() print("Generated Nonce:", nonce) return nonce
至此,所有配置完毕。
ps:也可以使用其他代理工具,只要能实现对应功能即可,比如mitmproxy代理工具
首先安装mitmproxy 的证书,才能抓包
- #启动监听端口
- mitmdump -p 9999
浏览器配置代理为127.0.0.1:9999 (可使用浏览器switchyOmega 扩展插件)
访问http://mitm.it获取对应证书,并双击安装

因为防重放的问题,需要所有讲经过mitmproxy的流量都配置不同的nonce头,故启动前执行脚本proxy.py
- import random
-
- def request(flow):
- # 生成随机 nonce 并设置为请求头
- flow.request.headers['nonce'] = str(random.randint(100, 999999))
mitmweb.exe -p 9999 -s proxy.py --set block_global=false --ssl-insecure
此时,mitmproxy的配置完成,可通过访问http://localhost:8081访问web管理界面
两处都需要配置,设置为mitmproxy的代理端口即可


将postman的代理端口设置为xray的即可

1、如果服务器必须使用https请求,这里涉及证书的问题,因为比较经过多层代理转发,xray可能会有tls连接失败的问题(后续测试,是没有在xray中的配置文件的mitm 的upstream_proxy 做配置的原因)
[ERRO] 2023-10-17 16:09:16 [sqldet:detector.go:307] Post "https://xxx.xxx.xxx.xxx/open/api/groups": remote error: tls: user canceled
目前推测还是证书的问题,还希望有大佬看到能详解。
ps:目前xray结合mitmproxy没有出现过相关问题,建议用这种方式