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都發送出去了。