Cookie安全小結

Cookie機制:通常來講,同域內瀏覽器中發出的任何一個請求都會帶上Cookie,不管請求什麼資源,請求時,Cookie出如今請求頭的Cookie字段中。服務端響應頭的Set-Cookie字段能夠添加、修改和刪除Cookie,客戶端經過javascript也能夠添加、修改和刪除Cookie。另外,Cookie是沒法跨瀏覽器存在的。javascript

利用Cookie機制,咱們能夠存儲用戶的會話信息,好比,用戶登認證後的Session,以後同域內發出的請求都會帶上認證後的會話信息,很方便。也所以,攻擊者特別喜歡盜取Cookie,這至關於盜取了目標網站上的用戶權限。php

固然,有時對靜態組件的Cookie讀取是一種浪費,咱們能夠用另外一個無Cookie的域名來存放這些靜態組件。java

Cookie的重要字段以下:瀏覽器

[name] [value] [domain] [path] [expries] [max-age] [httponly] [secure]安全

其含義依次爲:名稱、值、所屬域名、所屬相對根路徑、過時時間、是否有HttpOnly標誌、是否有Secure標誌。服務器

下面分別對domain、path 、httponly和secure字段進行說明:cookie

一、子域Cookie機制app

設置Cookie時,若是不指定domain的值,默認就是本域。dom

例如:a.foo.com域經過javascript設置一個Cookie,語句以下:測試

      document.cookie="test=1";

那麼,domain值默認爲a.foo.com。若是指定domain爲父級域,好比:

      document.cookie="test=1;domain=foo.com";

此時,domain變爲foo.com,這樣帶來一個好處就是能夠在不一樣的子域共享Cookie,壞處也很明顯,就攻擊者控制的其餘子域也能讀到這個Cookie。注意:這個機制不容許設置Cookie的domain爲下一級子域或其餘外域。

二、路徑Cookie機制

設置Cookie時,若是不指定path的值,默認就是目標頁面的路徑。

例如:a.foo.com/admin/index.php頁面經過javascript來設置一個Cookie,語句以下:

      document.cookie="test=1";

那麼,path值默認爲/admin/。經過指定path字段,javascript能夠設置任意Cookie到任意路徑下,可是隻有目標路徑下的頁面javascript才能讀取到該Cookie。

可是,經過設置path不能防止重要的Cookie被盜取。好比,/evil/路徑想讀取/admin/路徑的Cookie。經過跨iframe進行DOM操做便可作到,/evil/路徑下頁面的代碼以下:

 

xc=function(src){
    var o=document.createElement('iframe');//iframe進入同域的目標頁面
    o.src=src;
    document.getElementsByTagName('body')[0].appendChild(o);
    o.onload=function(){//iframe加載完成後
        d=o.contentDocument||o.contentWindow.document;//獲取document對象
        alert(d.cookie);//獲取cookie
    };
}('http://a.foo.com/admin/index.php');

三、HttpOnly Cookie機制

HttpOnly是指僅在HTTP層面上傳輸的Cookie,當設置了HttpOnly標誌後,客戶端腳本就沒法讀寫該Cookie,能有效地防護XSS攻擊獲取Cookie。以PHP setcookie爲例,httponly.php文件代碼以下:

<?php
setcookie("test",1,time()+3600,"","",0,0);    //設置普通cookie
setcookie("test_http",1,time()+3600,"","",0,1);//第7個參數(這裏的最後一個)是HttpOnly標誌,0爲關閉,1爲開啓,默認爲0
?>

請求這個文件後,設置了個兩個Cookie,以下圖所示:

 其中,test_http是HttpOnly Cookie。若是服務端響應的頁面有Cookie調試信息,極可能會致使HttpOnly Cookie的泄漏。好比如下信息。

 Apache HTTP Server2.2.x多個版本沒有嚴格限制HTTP請求頭信息,HTTP請求頭超過LimitRequestFieldSize長度時,服務器返回400(Bad Request)錯誤並在返回信息中將出錯的請求頭內容輸出(包含請求頭裏的HttpOnly Cookie),攻擊者能夠利用這個缺陷獲取HttpOnly Cookie。

大多數瀏覽器限制Cookies(每一個域50個Cookie)最大約爲4kB,咱們設置爲更大且爲本地Cookie,讓請求頭長度超過Apache的LimitRequestFieldSize,從而引發400錯誤。這樣受攻擊者只能經過清除Cookie才能正常訪問目標網站。

 

四、Secure Cookie機制

Secure Cookie機制指的是設置了Secure標誌的Cookie僅在HTTPS層面上安全傳輸,若是請求是HTTP的就不會帶上這個Cookie,這樣能下降重要的Cookie被中間人截獲的風險。

可是,Secure Cookie對於客戶端腳原本說是可讀寫的,也就意味着,它可以被盜取和篡改。以下的javascript腳本代碼可對已知的Secure Cookie進行篡改:

//path與domain必須一致,不然會被認爲是不一樣的Cookie
document.cookie="test_secure=1;path=/;secure;"

本地Cookie與內存Cookie

若是沒設置過時時間,就是內存Cookie,這樣的Cookie會隨着瀏覽器的關閉而從內存中消失;若是設置了過時時間是將來的某個時間點,那麼就是本地Cookie,這樣的Cookie就會以文本形式保存在操做系統本地,待過時時間到了纔會消失。如:

document.cookie="test_expires=1;expires=Mon,01 Jan 2112 00:00:00 GMT";//GMT時間,2112年1月1日纔會過時

採用本地Cookie可讓用戶在將來某一段時間內都不須要進行登陸操做,提高用戶體驗,可是,若是攻擊者經過XSS獲得這樣的本地Cookie後,就可以在將來很長一段時間內,甚至永久控制着目標用戶的帳號權限。但這並不意味着內存Cookie更安全,由於攻擊者能夠給內存Cookie加一個過時時間,使其變爲本地Cookie。

Cookie的P3P性質

HTTP響應頭的P3P(Platform for Privacy Preferences Project)字段是W3C公佈的一項隱私保護推薦標準。該字段用於標識是否容許目標網站的Cookie被另外一個域經過加載目標網站而設置或發送,但僅IE執行了該策略。

好比,evil域經過script或iframe等方式加載foo域。加載的時候,瀏覽器是否會容許foo域設置本身的Cookie,或是否容許發送請求到foo域時,帶上foo域已有的Cookie。

下面是關於P3P策略在設置與發送的兩個場景,P3P策略在這兩個場景下是有差別的:

一、設置Cookie

在IE下,默認是不容許第三方域設置Cookie(本地和內存)的,除非foo域在響應的時候帶上P3P字段,如:

P3P:CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"

該字段的內容自己意義不大,不須要記(固然咱們也沒有時間去記這些沒有特別意義的東西),只要知道這樣設置後,被加載的目標域的Cookie就能夠被正常設置了,設置後的Cookie在IE下會自動帶上P3P屬性(這個屬性在Cookie中是看不到的),一次生效,即便以後沒有P3P頭,也有效。

二、發送Cookie

發送的Cookie若是是內存Cookie,則無所謂是否有P3P屬性,就能夠正常發送;若是是本地Cookie,則這個本地Cookie必須擁有P3P屬性,不然,即便目標域響應了P3P頭也沒用。

咱們能夠經過如下方法進行測試:

1)給host文件添加www.foo.com與www.evil.com域。

2)將以下代碼保存爲foo.php,並保證能經過www.foo.com/cookie/foo.php訪問到。

<?php
//header('P3P:CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
setcookie("test0",'local',time()+3600*3650);
setcookie("test_mem0",'memory');
var_dump($_COOKIE);
?>

3)將以下代碼保存爲evil.php,並保證能經過www.evil.com/cookie/evil.php訪問到。

<iframe src="http://www.foo.com/cookie/foo.php"></iframe>

4)IE瀏覽器訪問www.evil.com/cookie/evil.php,因爲沒有響應P3P頭,foo.php設置並未成功。

5)將foo.php的P3P響應功能的註釋去掉,再訪問www.evil.com/cookie/evil.php,能夠發現本地Cookie(test0)與內存Cookie(test_mem0)都已設置成功。

6)修改foo.php裏的Cookie名,好比,test0改成test1,test_mem0改成test_mem1等,註釋P3P響應功能,而後直接訪問www.foo.com/cookie/foo.php,這時會設置本地Cookie(test1)與內存Cookie(test_mem1),此時這兩個Cookie都不帶P3P屬性。

7)再經過訪問www.evil.com/cookie/evil.php,能夠發現內存Cookie(test_mem1)正常發送,而本地Cookie(test1)沒有發送。

8)繼續修改foo.php裏的Cookie名,test1改成test2,test_mem1改成test_mem2,去掉P3P響應功能的註釋,而後直接訪問www.foo.com/cookie/foo.php,此時本地Cookie(test2)與內存Cookie(test_mem2)都有了P3P屬性。

9)這時訪問www.evil.com/cookie/evil.php,能夠發現test2與test_mem2都發送出去了。

相關文章
相關標籤/搜索