0x00 目录
文章首发先知https://xz.aliyun.com/t/15969
0x01前言
在某次渗透测试项目中拿到的资产前端采用了防重放机制,每一次请求都需要携带上新的验证参数,导致在bp重放的时候非常的麻烦,于是就只能想办法先解决这个问题再进行下一步。
笔者的思路是先解决签名的生成,再利用工具或脚本起到类似代理转发的功能,实现将burp发送的请求经过代理脚本后自动替换header中签名然后返回到burp中
用到的Burp的插件:https://github.com/f0ng/autoDecoder,该插件中的接口加解密功能完全符合我的需求。
0x02js代码分析
刚开始正常用bp抓包,然后放到重放模块发送发现不对劲,提示我参数无效,发现这参数在header中。看上去有点随机的样子,并且连带着跟着时间戳和Signature,直觉告诉我这三个应该是一起的。
直觉告诉我应该就是这了,打几个断点,刷新一下页面看看
成功断住,说到这里,其实根据这个参数的名字和值来看,有经验的师傅就会发现这其实就是uuid随机,验证也很简单,只要稍微跟进看一眼他生成的方式。
a的值在create()方法中生成
整个方法就是下面这部分代码了
由于传入的参数始终为空,也就是执行到这里始终调用n._create4方法,返回的就是一个uuid4的随机值
要是随机的话单凭这一个参数也无法做校验,再继续看下一个参数Signature
大概看一眼signature的生成方式,先判断请求方式,再将请求的param+&时间戳+&nonceStr+&key以字符串的形式拼接,再经过d()方法生成签名
直接跟进d()的话没找到具体的加密代码,这里我用控制台执行d()的方法,可以看到d()的返回值。双击跟进一下
那应该就是直接md5了,拿o在线加密对比一下发现确实是的
到这里对三个参数的生成方式已经清楚了
Timestamp: 时间戳
Noncestr:uuid4
Signature: md5(param+时间戳+nonceStr+key)
先写个简单的脚本测试一下能否正确生成签名
PS:在写脚本测试的时候发现时而可以时而不行,也是折腾了半天,最后在调试的时候对比参数o的时候发现代码对截取的get请求的参数还进行了一个排序功能。。。
同时对于POST请求的话,由于站点基于POST传入的都是json数据,对于json数据处理就没有get请求那样复杂,也是直接拼接就行。
到这里前端js防重放签名的生成已经解决,但还是得不断的手动复制粘贴参数,想想都觉得累啊,于是下一步要解决的就是自动替换的问题。
0x03BP插件+Flask实现自动加解密替换
原本的思路就是准备写一个实现代理监听服务脚本,流量经过的时候自动修改替换请求头中的签名参数,但是最主要的问题是bp重放模块如何一键自动发送到我们起的监听服务中呢。
然后发现了有个工具能够实现这样的功能
工具链接:https://github.com/f0ng/autoDecoder
用上原项目中的一张图
正好是我们需要的功能,只不过是把自动加解密换成了自动添加header头的功能,实现这个功能用到的是其中的接口加解密,翻看一番工具的使用之后,按照我们需要的功能写个对应的Flask服务
下面是原作者给出的编写模板,我们稍微改一下:
from flask import Flask,Response,request
from pyDes import *
import base64
app = Flask(__name__)
def encrypt():
body = request.form.get('dataBody') # 获取 post 参数 必需
headers = request.form.get('dataHeaders') # 获取 post 参数 可选
if headers != None: # 开启了请求头加密
headers = headers + "aaaa:bbbbrn"
headers = headers + "f0ng:test"
print(headers + "rnrnrnrn" + body)
return headers + "rnrnrnrn" + body # 返回值为固定格式,不可更改
return body
def decrypt():
body = request.form.get('dataBody') # 获取 post 参数 必需
headers = request.form.get('dataHeaders') # 获取 post 参数 可选
if headers != None: # 开启了响应头加密
print(headers + "rnrnrnrn" + body)
headers = headers + "yyyy:zzzzrn"
headers = headers + "f0ng:onlysecurity"
return headers + "rnrnrnrn" + body # 返回值为固定格式,不可更改
return body
if __name__ == '__main__':
app.debug = True # 设置调试模式,生产模式的时候要关掉debug
app.run(host="0.0.0.0",port="8888")
改好后直接运行服务:
0x04Bp配置插件
接下来再上bp加载配置下该插件
我们只需要使用到接口加解密模块,这里的解密接口对应的就是返回包的处理,加密接口对应的是请求包的处理,填好对应的加解密接口
由于不知道是不是bp版本的原因,本人在使用的时候重放模块一直加载不出该插件,最后发现要先在选项界面保存一下配置才行.
然后调试一下能不能正常替换
输出台显示已经成功添加上新的签名
bp重放成功
但是问题又来了,发现中文居然乱码了。。
虽然并不影响挖漏洞,但是看起来很不爽啊
python调试输出一下返回包的内容,发现python中是正常的,但是响应的内容再发送到burp的时候就乱码了.
针对这个问题上网搜了一下,很大概率是编译的时候系统选用的字符集和使用的不一样,于是尝试重新编译一下,就不细说了
然后再重新加载一遍插件
ok了,到这里已经是正常显示了,接下来就可以正常的开始测漏洞了.
0x05漏洞挖掘
前面解决这个问题就花了不少时间,留给我的时间已经不多了。测了半天发现基本上都防范的差不多了,fuzz接口也没有什么成功
这时候在测试某个功能点的时候,突然发现跳转到另一个域名了,但是界面和接口都是相同的,并且泄露了接口文档,并且返回的数据包中提示这是测试环境
这思路不就来了吗,应该是开发把测试站开了,直接先把接口先弄下来,防止等下它把测试站关了
这工具还有一个优点就是可以Intruder和插件扩展都可以直接使用自动加解密功能,非常的人性化,勾中选项就好了
于是把测试站搞到的接口直接fuzz一下,看看哪些能用的
这一看还不少,而且内容还挺多,有了有了
后面的其他漏洞就不细说了。
0x06小结
由于防重放的站点还是有不少,如果是资产多的情况下一般都放弃了,但是恰恰是这样,开发人员可能觉得做了防重放或者其他的一些比如参数加密这样的操作,对系统的安全性就没有那么的严谨,只要绕过它的前端加密,后面漏洞测试就比较简单了。
那么本次遇到的站点主要是针对header请求头中的防重放签名进行绕过,利用bp插件+脚本实现自动替换的功能。这个工具的接口加解密功能用处可以说还是用处很广的,针对一些不常见的加解密无法用自带模块加解密的话,就可以自己扣脚本出来处理。
原文始发于微信公众号(小呆安全):【实战小技巧系列】记某次bp插件+flask自动替换绕过防重放的高危漏洞挖掘
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论