一、问题引入: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 stringclass 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 headersdef 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
目前推测还是证书的问题,还希望有大佬看到能详解。