一、问题引入:api接口测试,会检测请求头中的nonce参数的值,每次请求的值必须不同,否则发包失败
笔者在进行api接口的测试时(因为菜没有工具,只能另辟蹊跷),使用postman+xray进行安全测试,但是因为nonce参数检测的缘故,导致xray的发出的扫描包全部失效,导致无法使用xray进行安全扫描,由此引入问题。
二、解决思路
2.1 给xray配置http请求的Header头的nonce参数(pass)
这种方式,流量走向还是 postman --> xray --> 服务器
查看xray的配置文件,我的版本为1.9,配置文件config.yaml
但是在这个配置文件中,headers的配置的值是静态的,nonce的值并不能动态变化,也就是说每次发包的nonce值还是一致的,并没有解决问题。此条思路pass,或者是我理解的不够,没有配置好,希望知道的大佬告知一声。
2.2 在xray之后再配置一条代理,流量postman-->xray-->代理--> 服务器
后来决定另辟一条线,就是给xray加代理,在xray的上层代理处将xray发出扫描的扫描请求包的header头中nonce替换掉,已实现绕过api防止重放的验证。
在xray的配置文件中配置代理即可,当前xray支持 https http socket5的代理
三、实践(postman --> xray --> burpsuite --> 服务器)
我这里为了实现上述的解决方案,用了postman+xray+burpsuite的结局方案。
整理思路及配置如下:
-
1、postman配置代理为xray
-
2、主机安装xray和burp的证书
双击对应的证书文件即可
-
3、xray配置代理为burpsuite监听端口
-
4、burp创建扩展脚本(当前bp版本为2023.1),将所有请求包的nonce参数的值替换
# -*- 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代理工具
四、可能存在的问题
1、如果服务器必须使用https请求,这里涉及证书的问题,因为比较经过多层代理转发,xray可能会有tls连接失败的问题
[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
目前推测还是证书的问题,还希望有大佬看到能详解。