<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/tips/151

            同源策略


            同源策略的文檔模型

            同源策略(Same Origin policy,SOP),也稱為單源策略(Single Origin policy),它是一種用于Web瀏覽器編程語言(如JavaScript和Ajax)的安全措施,以保護信息的保密性和完整性。

            同源策略能阻止網站腳本訪問其他站點使用的腳本,同時也阻止它與其他站點腳本交互。

            原始資源 要訪問的資源 非IE瀏覽器 IE瀏覽器
            http://example.com/a/ http://example.com/b/ 可以訪問 可以訪問
            http://example.com/ http://www.example.com/ 主機不匹配 主機不匹配
            http://example.com/a/ https://example.com/a/ 協議不匹配 協議不匹配
            http://example.com:81/ http://example.com/ 端口不匹配 可以訪問

            同源策略一開始是為了管理DOM之間的訪問,后來逐漸擴展到Javascript對象,但并非是全部。

            例如非同源的腳本之間可以調用location.assign()和location.replace()。

            同源策略在提高了安全性,但同時也降低了靈活性。

            例如很難將login.example.com與payments.example.com兩個域之間的數據可以方便的傳送。

            介紹兩種解決方式:document.domain和postMessage()。

            javascript允許子域之間使用頂級域名。

            例如login.example.com和payments.example.com都可以進行如下設置:

            document.domain="example.com"
            

            設置這個屬性之后,子域之間可以方便的通信,需注意的是協議和端口號必須相同。

            原始資源 訪問的資源 結果
            URL document.domain URL document.domain
            http://www.example.com/ example.com http://payments.example.com/ example.com 可以訪問
            http://www.example.com/ example.com https://payments.example.com/ example.com 協議不匹配
            http://payments.example.com example.com http://example.com/ (不設置) 拒絕訪問
            http://www.example.com/ (不設置) http://www.example.com example.com 拒絕訪問

            postMessage()是HTML5的一個API接口,由于比較新,所以在IE6和IE7中不支持。 1 向另外一個iframe發送消息:

            var message = 'Hello' + (new Date().getTime());
                window.parent.frames[1].postMessage(message, '*');
            

            iframe1.html需要向iframe2.html發送消息,也就是第二個iframe,所以是window.parent.frames[1]。

            如果是向父頁面發送消息就是window.parent。

            postMessage這個函數接收二個參數,缺一不可,第一個參數即你要發送的數據。

            第二個參數是非常重要,主要是出于安全的考慮,一般填寫允許通信的域名。

            這里為了簡化,所以使用’*',即不對訪問的域進行判斷。

            2 另外一個iframe監聽消息事件:

            iframe2.html中寫個監聽message事件,當有消息傳到iframe2.html時就會觸發這個事件。
            var onmessage = function(e) {
                var data = e.data,p = document.createElement('p');
                p.innerHTML = data;
                document.getElementById('display').appendChild(p);
            };
             //監聽postMessage消息事件
            if (typeof window.addEventListener != 'undefined') {
                window.addEventListener('message', onmessage, false);
             } else if (typeof window.attachEvent != 'undefined') {
                window.attachEvent('onmessage', onmessage);
            }
            

            如果你有加域名限,比如下面的代碼:

            window.parent.frames[1].postMessage(message, 'http://www.test.com');
            

            就要在onmessage中追加個判斷:

            if(event.origin !== 'http://www.test.com') return;
            

            XMLHttpRequest的同源策略

            一個簡單的同步XMLHttpRequest請求:

            var x = new XMLHttpRequest();
            x.open("POST", "/some_script.cgi", false);
            x.setRequestHeader("X-Random-Header", "Hi mom!");
            x.send("...POST payload here...");
            alert(x.responseText);
            

            XMLHttpRequest請求嚴格遵守同源策略,非同源不可以請求。

            這個API也做過很多測試與改進,下面列出之前的測試方法:

            var x = new XMLHttpRequest();
            x.open("POST", "http://www.example.com/", false);
            // 定義發送內容長度為7
            x.setRequestHeader("Content-Length", "7");
            // 構造的http請求。
            x.send(
            "Gotcha!\n" +
            "GET /evil_response.html HTTP/1.1\n" +
            "Host: www.bunnyoutlet.com\n\n"
            );
            

            現在的瀏覽器都不存在上面的隱患,包括基本都禁用了TRACE方法,防止httponly的cookie泄漏問題等。

            Web Storage的同源策略

            Web Storage是由Mozilla的工程師在Firefox1.5中加入的,并且加入了HTML5中,現在的瀏覽器都支持,除了IE6與IE7。

            JavaScript可以通過localStorage與sessionStorage對Web Storage進行創建,檢索和刪除:

            localStorage.setItem("message", "Hi mom!"); 
            alert(localStorage.getItem("message")); 
            localstorage.removeItem("message");
            

            localStorage對象可以長時間保存,并且遵守同源策略。

            但是在IE8中localStorage會把域名相同但是協議分別為HTTP和HTTPS的內容放在一起,IE9中已修改。

            在Firefox中,localStorage沒有問題,但是sessionStorage也是會把域名相同的HTTP與HTTPS放在一起。

            Cookie的安全策略

            設置Cookie總結

            在foo.example.com設置cookie,domain設置為:

            最終cookie的范圍

            非IE瀏覽器

            IE瀏覽器

            設置為空

            foo.example.com(一個域)

            *.foo.example.com

            bar.foo.example.com

            cookie設置失敗,設置的域是當前域的一個子域

            foo.example.com

            *.foo.example.com

            baz.example.com

            cookie設置失敗,域名不匹配

            example.com

            *.example.com

            ample.com

            cookie設置失敗,域名不匹配

            .com

            設置失敗,域名太廣,存在安全風險。

            Cookie中的path參數可以設定指定目錄的cookie。

            例如設定domain為example.com,path為/some/path/ 在訪問下面url的時候會帶上設定的cookie:

            http://foo.example.com/some/path/subdirectory/hello_world.txt

            存在一定的安全風險,因為path的設定沒有考慮到同源策略。

            httponly屬性可以防止通過document.cookie的API訪問設定的cookie。

            secure屬性設定后只有在通過https傳輸時才會帶上設定的cookie,可以防止中間人攻擊。

            Adobe Flash

            AllowScriptAccess參數:用來控制flash通過ExternallInterface.call()函數調用javascript的時的限制。

            有三個值:always,never和sameorigin,最后一個值只允許同域的JavaScript操作(08年之前默認為always,現在默認為sameorigin)。

            AllowNetworking參數:用來控制flash與外部的網絡通訊。

            可選的值為:all(允許使用所有的網絡通訊,默認值),internal(flash不能與瀏覽器通訊如navigateToURL,但是可以調用其他的API),none(禁止任何的網絡通訊)

            本地文件

            由于本地文件都是通過file:協議進行訪問的,由于不存在host,所以無法遵循同源策略。

            所以本地保存的一個HTML文件,在瀏覽器中通過file:協議訪問后,可以通過XMLHttpRequest或DOM對本地其他文件進行操作。

            與此同時,也可以對互聯網的其他資源做同樣的操作。各瀏覽器廠商意識到這個問題,并努力做了修改:

            測試代碼:

            1.html(1.txt隨機寫一些字符串即可)

            <script>
            function createXHR(){
              return window.XMLHttpRequest?
              new XMLHttpRequest():
              new ActiveXObject("Microsoft.XMLHTTP");
            }
            function getlocal(url){
              xmlHttp = createXHR();
              xmlHttp.open("GET",url,false);
              xmlHttp.send();
              result = xmlHttp.responseText;
              return result;
            }
            function main(){
              url = "file://路徑/1.txt";
              alert(url);
              result = getlocal(url);
              alert(result);
            }
            main();
            </script>
            

            結論:

            1 Chrome瀏覽器(使用WebKit內核的瀏覽器)
            完全禁止跨文檔的XMLHttpRequest和DOM操作,并禁止了document.cookie和<meta http-equiv="Set-Cookie" ...>的操作。
            2 Firefox
            允許訪問同目錄與子目錄里的文件。也可通過document.cookie與<meta http- equiv="Set-Cookie" ...>設定cookie,file:協議下cookie共享,storage也是。
            3 IE7及以上
            允許本地文件之間的訪問,但是在執行JavaScript之前會有一個提示,用戶點擊通過之后可以執行,cookie域Firefox類似,但是file:協議下不支持storage。
            4 IE6
            允許本地文件的訪問,同時也允許對http協議的訪問,cookie也是一樣。
            

            偽URL的域


            一些web應用用到了偽URL例如about:,javascript:,和data:來創建HTML文檔。

            這種方法是為了不需要再與服務器通信,可以節約時間更快的響應,但是也帶進了很多安全隱患。

            about:blank
            

            about協議在現在的瀏覽器中有很多用途,但是其中大部分不是為了獲取正常的頁面。

            about:blank這個URL可以用來被創建DOM對象,例如:

            <iframe src="about:blank" name="test"></iframe>
            <script> 
            frames["test"].document.body.innerHTML = "<h1>Hi!</h1>";
            </script>
            

            在瀏覽器中,創建一個about:blank頁面,它繼承的域為創建它的頁面的域。

            例如,點擊一個鏈接,提交一個表單,創建一個新窗口,但是當用戶手動輸入about:或者書簽中打開的話,他的域是一個特殊的域,任何其他的頁面都不可以訪問。

            data:協議
            

            data:協議是設計用來放置小數據的,例如圖標之類的,可以減少http請求數量,例如:

            <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEBLAEsAAD...">
            

            用以下代碼研究域的問題:

            <iframe src="data:text/html;charset=utf-8,<script>alert(document.domain)</script>" >  
            

            在Chrome與Safari中,所有的data:都會賦予一個單獨的,不可獲取的域,而不是從父域中繼承的。

            Firefox與Opera中,域是繼承于當前頁面。

            IE8之前的版本不支持data:協議。

            javascript:和vbscript:

            javascript:協議允許后面執行javascript代碼,并且繼承了調用的當前域。

            有些情況會對后面的內容處理兩次,如果代碼正確的話,會把后面的代碼當成html解析,覆蓋掉原來的html代碼:

            <iframe src='javascript:"<b>2 + 2 = " + (2+2) + "</b>"'> 
            </iframe>
            

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

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

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

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

                      亚洲欧美在线