在漫漫滲透之路中,眼前一亮的發現一個站。Referer字段沒有檢查,POST參數中的動態token也沒有檢查,這不是帶一波CSRF的節奏嘛。但是遇到一個之前我沒遇到的問題導致我CSRF失敗,這個問題或許很簡單,但是我是一個小白,大牛看到就不要噴我了。
首先我在Burpsuite當中生成了CSRF的POC,發現不行。經過與原始請求對比發現HEADER中少了一個字段,而這個字段就是CSRF成敗與否的關鍵。下面開始不啰嗦上真正知識點。
在原來站中這個請求是一個POST的Ajax異步請求。於是在HTTP報文的head頭里面就有了這個字段:X-Requested-With: XMLHttpRequest。 服務器明顯檢查了這個字段,帶有的這個字段就會成功,否則就會302重定向到登錄頁面。於是我構造了一個利用xmlhttprequest 夠早了一個POC。
#注釋內容(python是最好的語言,至少在我心中如此):
"""
xmlhttprequest帶cookie的方案:
var xhr = new XMLHttpRequest(); xhr.open("POST", "http://xxxx.com/demo/b/index.php", true); xhr.withCredentials = true; //支持跨域發送cookies
xmlhttprequest設置head頭字段:
xhr.setRequestHeader("POWERED-BY-MENGXIANHUI", "Approve"); xhr.setRequestHeader("Content-Type", "application/xml");
"""
於是我想這樣可以了吧,然后就發起了新的Ajax請求准備CSRF,但是在Burp中看到,沒有字段。
原因:X-Requested-With: XMLHttpRequest在跨域請求中會被去掉(如果跨域配置允許時候可以帶着,看配置)。
然后我手動強制加上了這個字段:
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
這個時候我發現,原來的報文變成了OPTION包,而不是POST請求報文。
原來這是跨域訪問的一種安全檢查機制:
首先發起OPTION對目標服務器進行測試,看看這種訪問是否安全
在頭部字段會出現下面三個
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with
Origin: null(跨域Ajax去掉X-Requested-With,帶上這個)
當收到服務器端的響應允許后才發送正式POST或者GET請求。
這叫做預檢報文,如何不觸發預檢報文,有三個同時滿足的必備條件(三項均成立才行):
1. 只能是Get、Head、Post方法
2. 除了瀏覽器自己在Http頭上加的信息(如Connection、User-Agent),開發者只能加這幾個:Accept、Accept-Language、Content-Type……
3. Content-Type只能取這幾個值:
application/x-www-form-urlencoded
multipart/form-data
text/plain
或許有相關的解決辦法,我后面研究研究繼續搞。