1. 程式人生 > >【XSS技巧拓展】————1、漫談同源策略

【XSS技巧拓展】————1、漫談同源策略

摘要

如今的WEB標準紛繁複雜,在瀏覽稍大一些的網站時,細心的人會發現網頁上呈現的內容並不僅限於網站自身提供的內容,而是來自一堆五花八門的網站的內容的集合。但有誰會想到同源策略在保護著網民們的安全呢?

瞭解同源策略是十分有必要的,要深入掌握XSS / CSRF等WEB安全漏洞,不瞭解同源策略就如同盲人摸象一般,無法說出全貌,更無法應用其進行打擊。另外,無論是網銀盜號,還是隱私洩露,理解了同源策略,就有助於理解自己面臨著什麼樣的威脅。

0x00 什麼是源和同源策略

源就是主機,協議,埠名的一個三元組。

同源策略(Same Origin Policy, SOP)是Web應用程式的一種安全模型,它控制了網頁中DOM之間的訪問。重要的事情說三遍,它只是個模型,而不是標準(哪怕標準在實現的時候也會千差萬別)。同源策略被廣泛地應用在處理WEB內容的各種客戶端上,比如各大瀏覽器,微軟的Silverlight,Adobe的Flash/Acrobat等等。SOP影響範圍包括:普通的HTTP請求、XMLHttpRequest、XSLT、XBL。

0x01 如何判斷同源

定義:給定一個頁面,如果另一個頁面使用的協議、埠、主機名都相同,我們則認為兩個頁面具有相同的源。 舉個例子,我們假設需要比對的目標頁面來自這個URI: http://sub.eth.space/level/flower.html 

0x02 同源策略究竟限制了什麼?

首先,我們要明確同源策略只作用在實現了同源策略的WEB客戶端上。 雖然筆者不常用百度,但是我們來看一個具有誤導性的結論:百度詞條對於同源策略的解釋說“只有和目標同源的指令碼才會被執行”,這是不對的,同源策略沒有禁止指令碼的執行,而是禁止讀取HTTP回覆。 更正了這個概念之後,我們會發現,SOP其實在防止CSRF上作用非常有限,CSRF的請求往往在傳送出去的那一瞬間就已經達到了攻擊的目的,比如傳送了一段敏感資料,或請求了一個具體的功能,是否能讀取回復並不那麼重要(唯一的作用是可以防止CSRF請求讀取異源的授權Token)。 另外,一般靜態資源通常不受同源策略限制,如js/css/jpg/png等。

0x03 跨源的網路訪問

為什麼要起這麼拗口的名字:網路訪問?因為WEB上資源訪問的多樣性,不能簡單的稱之為網路請求。大體看來我們有三種類型:

跨域寫通常被允許,例如連結,重定向和表單提交,一些不常見的HTTP請求方法例如PUT,DELETE等需要先發送預請求(preflight),例如傳送OPTIONS來查詢可用的方法。

跨域嵌入,通常被允許。

跨域讀,通常被禁止,然而,我們可以用其他方法達到讀取的效果。

一個經久不衰的BUG

早在2011年,一個使用者在Mozilla的Bug追蹤系統中就提交了一個issue,聲稱他可以判定某個網站的訪客是否登入了gmail,facebook等等。

嵌入iframe來獲取一個訪問網站的使用者是否登陸了gmail:

<ol class="linenums">
    <li class="L0">
        <span class="tag">
            <img</span>
            <span class="pln"> </span>
            <span class="atn">style</span>
            <span class="pun">=</span>
            <span class="atv">"</span>
            <span class="pln">display</span>
            <span class="pun">:</span>
            <span class="pln">none</span>
            <span class="pun">;</span>
            <span class="atv">"</span>
            <span class="pln">  </span></li>
            <li class="L1">
            <span class="pln"> </span>
            <span class="atn">onload</span>
            <span class="pun">=</span>
            <span class="atv">"</span>
            <span class="pln">logged_in_to_gmail</span>
            <span class="pun">()</span>
            <span class="atv">"</span></li>
            <li class="L2">
            <span class="pln"> </span>
            <span class="atn">onerror</span>
            <span class="pun">=</span>
            <span class="atv">"</span>
            <span class="pln">not_logged_in_to_gmail</span>
            <span class="pun">()</span>
            <span class="atv">"</span></li>
            <li class="L3">
            <span class="pln"> </span>
            <span class="atn">src</span>
            <span class="pun">=</span>
            <span class="atv">"https://mail.google.com/mail/photos/img/photos/public/AIbEiAIAAABDCKa_hYq24u2WUyILdmNhcmRfcGhvdG8qKDI1ODFkOGViM2I5ZjUwZmZlYjE3MzQ2YmQyMjAzMjFlZTU3NjEzOTYwAZwSCm_MMUDjh599IgoA2muEmEZD"</span></li>
            <li class="L4">
        <span class="tag">/></span>
    </li></ol>

src的程式碼試圖訪問一張gmail中攻擊者上傳的圖片,如果使用者沒有登陸gmail,就無法成功載入。從而達到判斷使用者是否登陸gmail的效果。這種方法可以推廣到任何對不應跨源訪問的資源沒有正確設定同源策略的網站。

0x04 談談攻擊

作為一個抽象的WEB安全模型,每個處理WEB內容的客戶端實現的都不完全一樣,這就帶來了許多差異點,而差異點的存在就帶來了漏洞,正所謂“千里之堤,潰於蟻穴”。

對URI的解析

IP是URI的重要組成部分,如果留心了RFC的人就會知道,IP不止有一種格式。下面的標註形式其實都代表了同一個IP:216.58.209.68,大家可以在瀏覽器裡實驗。

<ol class="linenums">
    <li class="L0">
        <span class="lit">216.58</span>
        <span class="pun">.</span>
        <span class="lit">53572</span>
    </li>
    <li class="L1"><span class="lit">0xD8</span>
        <span class="pun">.</span>
        <span class="lit">072.53572</span>
    </li>
    <li class="L2">
        <span class="lit">3627733316</span>
    </li>
    <li class="L3">
        <span class="lit">0330.3854660</span>
    </li>
</ol>

當某些瀏覽器對URI的解釋存在漏洞的時候,就可以構造出有趣的攻擊鏈來繞過SOP。 比如CVE-2015-7188火狐瀏覽器SOP繞過中。攻擊者構造了特殊的URL,並在攻擊者自己控制的來自37.187.18.85的網頁中發起跨域請求

http://37.187.18.85\0B\uFF20translate.google.com/fx_sop_bypass/FlashTest.swf?url=http://translate.google.com/manager/website/    

先通過\0B讓Firefox認為這個請求是請求37.187.18.85本身的內容,再通過類似@字元的Unicode字元@(\uFF20)讓瀏覽器認為@之前的字元都是translate.google.com的賬號和密碼,從而返回translate.google.com的網頁內容,實現繞過SOP。

設計缺陷導致SOP繞過

在Java6,7中,如果兩個域名解析到相同的IP,則會認為他們同源。假設我們有attacker.com和victim.com,兩者都共享主機123.123.123.123。攻擊者attacker.com可以在自己控制的域名下上傳一個jar檔案來訪問victim.com的內容。

訪問本地檔案的同源策略

不同的瀏覽器使用不同的瀏覽器引擎,而不同的引擎對於同源策略的處理也並非完全一致。例如,Firefox使用Gecko瀏覽器引擎,在古老的Gecko1.8版(Firefox3)之前,任意兩個file://的URI都被認為是同源的,意思就是,任意本地HTML檔案將有許可權訪問本地計算機上任意其他檔案。如今的Gecko版本中,一個HTML文件只能訪問其所在資料夾下的其他檔案。 對於跨越視窗的DOM訪問,每個檔案被當作一個單獨的源,除了一種情況:當一個檔案被另一個檔案可以用同源策略訪問時,視為相同的源。

<ol class="linenums">
    <li class="L0">
        <span class="com"><!-- 檔案路徑:/home/user/1.html -->
            
        </span>
        <span class="pln">  </span>
    </li>
    <li class="L1">
        <span class="tag">
            <html>
        </span>
        <span class="pln"> 
        </span>
    </li>
    <li class="L2">
        <span class="tag">
            <frameset</span>
            <span class="pln"> </span>
            <span class="atn">cols</span>
            <span class="pun">=</span>
            <span class="atv">"50%,*"</span>
            <span class="tag">></span>
            <span class="pln">  </span>
    </li>
    <li class="L3">
        <span class="pln">  </span>
        <span class="tag"><frame</span>
        <span class="pln"> </span>
        <span class="atn">src</span>
        <span class="pun">=</span>
        <span class="atv">"/home/user/dir/2.html"</span>
        <span class="tag">></span>
    </li>
    <li class="L4">
        <span class="pln">  </span>
        <span class="tag">
        <frame</span>
        <span class="pln"> </span>
        <span class="atn">src</span>
        <span class="pun">=</span>
        <span class="atv">"..."</span>
        <span class="tag">></span>
    </li>
    <li class="L5">
        <span class="tag">
        </frameset></span>
        <span class="pln">  </span>
    </li>
    <li class="L6">
        <span class="tag">
            </html>
        </span>
    </li>
</ol>

上圖中,1.html和2.html被視為相同的源。

<ol class="linenums">
    <li class="L0">
        <span class="com"><!-- 檔案路徑:/home/user/dir/1.html -->
            
        </span>
        <span class="pln">  </span>
    </li>
    <li class="L1">
        <span class="tag">
            <html>
        </span>
        <span class="pln">  </span>
    </li><li class="L2">
        <span class="tag">
            <frameset</span>
            <span class="pln"> </span>
            <span class="atn">cols</span>
            <span class="pun">=</span>
            <span class="atv">"50%,*"</span>
            <span class="tag">></span>
            <span class="pln">  </span>
        </li><li class="L3">
            <span class="pln">  </span>
            <span class="tag"><frame</span>
            <span class="pln"> </span>
            <span class="atn">src</span>
            <span class="pun">=</span>
            <span class="atv">"/home/user/2.html"</span>
            <span class="tag">></span>
        </li>
        <li class="L4">
            <span class="pln">  </span>
            <span class="tag">
                <frame</span><span class="pln"> </span>
                <span class="atn">src</span>
                <span class="pun">=</span>
                <span class="atv">"..."</span>
                <span class="tag">></span>
            </li>
        <li class="L5">
            <span class="tag">
            </frameset></span>
            <span class="pln">  </span>
        </li>
        <li class="L6">
            <span class="tag">
                </html>
            </span>
        </li>
    </ol>

上圖中,1.html和2.html被視為異源。

特立獨行的Internet Explorer

在IE中,有兩種情況同源策略無效:

TrustZones(信任域)當一個URI被加入到了IE的信任網站區域中時,瀏覽器會無視同源策略。

IE在考慮同源策略時不包括埠, 這意味著不同埠上的應用程式可以讀取到比如使用者的登陸賬戶密碼/cookie等。

通過變更自身的源繞過同源策略

IE 6,7版中網頁可以通過document.domain設定自身的來源為任意其他來源。如今網頁仍然可���更改源,但是有一些限制。

網頁可以變更自身的源為父級域名。

例如http://malicious.eth.space/1.html可以通過執行

<ol class="linenums">
    <li class="L0">
        <span class="pln">document</span>
        <span class="pun">.</span>
        <span class="pln">domain </span>
        <span class="pun">=</span>
        <span class="pln"> </span>
        <span class="str">"eth.space"</span>
        <span class="pun">;</span>
    </li>
</ol>

來繞過同源策略的限制,從而可以讀取http://eth.space/login.html上的內容。這其中的應用大家可以自己去想。

注意埠不同的情況。

需要注意的是,在改變源時,埠號是需要特別指定的。由於執行以下js程式碼

<ol class="linenums">
    <li class="L0">
        <span class="pln">document</span>
        <span class="pun">.</span>
        <span class="pln">domain </span>
        <span class="pun">=</span>
        <span class="pln"> document</span>
        <span class="pun">.</span>
        <span class="pln">domain</span>
    </li>
</ol>

將會導致埠號被重置為null。���以源http://eth.space:1337不能通過修改document.domain="eth.space"來訪問http://eth.space的資料,除非後者也設定了document.domain="eth.space",這樣雙方的源埠號才能一致(null)。反之亦然。

0x05 談談防禦

如何安全地允許跨源訪問?

  • 最好的方式是使用CORS,跨源資源共享機制。這個需要的篇幅挺大,我們有機會下次講。
  • 使用Window.postMessage
  • 使用JSONP。

如何禁止(你的資源被)跨源訪問?

  • 為了禁止跨域寫,我們需要引入CSRF令牌,然而我們需要正確的配置同源策略,否則CSRF令牌本身也將被惡意網頁讀取。
  • 為了禁止跨域讀,我們可以通過設定X-Frame-Options頭來禁止該頁面被嵌入到惡意頁面中,就如同在“經久不衰的BUG”中一樣。
  • 為了禁止跨域嵌入,確保你的資源本身無法嵌入到各種跨域訪問方式中,比如<script src=></script> <img src=x></img>,<svg onload=>,各種字型載入等等。同時,使用CSRF令牌也可以有效避免被跨域嵌入。

如何禁止你控制的網頁中嵌入的iFrame做出惡意行為?

使用HTML5的沙盒iframe。

先寫到這裡吧,事實上,WEB安全中還有幾個重要的機制,例如和同源策略相輔相成的跨域資源共享機制(CORS),和內容安全策略(Content Security Policy, CSP)下次再寫。

轉自:https://www.360zhijia.com/360anquanke/199499.html