理解Cookie和Session機制,及其安全問題

雲牧青發表於2022-01-13




Cookie和Session的區別?百度一下最常見的就是"Cookie儲存在客戶端而Session儲存在服務端",很多人看了有疑惑,明明Session就在Cookie中啊,為什麼這麼說?二者到底有啥區別?



一、Cookie

首先分清Cookies和Cookie

Cookies嚴格來說是個儲存空間,是個載體,用提交持久化的資訊,瀏覽器傳送HTTP請求時會自動帶上此域的所有Cookie,抓包能發現就在HTTP Header中

Cookie就是儲存在Cookies中的一條條資料

但當我們說Cookie和Session的區別時,這裡的Cookie就理應是一種和Session一樣的認證機制,這種情況下Session藉助Cookies暫存在瀏覽器中,二者都在瀏覽器和伺服器中被儲存,這是Cookies最重要的應用

那如何解釋"Cookie儲存在客戶端"呢?可能本來就是瞎說,也可能是最開始有這種場景:

網站設計時,服務端可能每次收到請求都需要知道客戶端的某種資訊,比如使用者登入時間,這種資訊又不足以重要到需要儲存在服務端,那麼可以藉助Cookie

資料在前端生成,或在服務端生成,生成後通過Set-Cookie傳送給客戶端後,服務端自身不儲存,當客戶端再次有請求時,服務端可以從請求的HTTP Header中調出這個資料

以及傳聞中cookie名字的由來:

設想你某次登陸過一個網站,下次登入的時候不想再次輸入賬號了,怎麼辦?這個資訊可以寫到Cookie裡面,訪問網站的時候,網站頁面的指令碼可以讀取這個資訊,就自動幫你把使用者名稱給填了,能夠方便一下使用者。這也是Cookie名稱的由來,給使用者的一點甜頭。

我比較認可的解釋是Session是在服務端儲存的一個資料結構,用來跟蹤使用者的狀態,這個資料可以儲存在叢集、資料庫、檔案中;Cookie是客戶端儲存使用者資訊的一種機制,用來記錄使用者的一些資訊,也是實現Session的一種方式[1]



二、Session

Session是身份認證的憑證,使用者登入後,伺服器分發一個憑證,以後使用者再請求帶上這個憑證就能明確身份,不用每次都用賬號密碼來證明身份

這麼重要的資料當然得儲存在服務端,且以服務端的為準。但客戶端也得儲存,才能在登入週期中每次請求都帶上

"每次請求都帶上"這顯然就和Cookie一樣,所以就有很多開發者把Session放在Cookies裡,不用自己寫前端程式碼把Session塞進請求裡,瀏覽器自己會帶上

而瀏覽器開發者也覺得這樣很合理,也為Cookie新增了一些可設定的安全相關屬性



三、Cookies中使用者憑證的安全問題

目前的瀏覽器有以下空間供網站使用

  • Cookies:持久儲存,大小限制4kb,最多放20個,每次請求都會帶上所有Cookie

  • Session Storage:關閉標籤後失效,請求不會主動帶上

  • Local Storage:持久儲存,請求不會主動帶上

我們再來看幾個Web的安全漏洞

  • XSS,跨站指令碼攻擊。攻擊者獲得頁面的js許可權,能操作頁面的一切,包括Session Storage和未設定HTTP Only屬性的Cookie

  • CSRF,跨站請求偽造,就是釣魚網站,在網站A,傳送一個向網站B的請求,由於瀏覽器會在請求中加上此域的Cookie,所以如果在瀏覽器登入了網站B,又開啟了釣魚網站A,網站A構造的前往網站B的請求就會帶上你的Cookie,如果Cookie中有使用者憑證,伺服器認為你是登入使用者,請求就會被響應。比如點贊、關注、髮色情廣告等請求

防禦XSS,把關機Cookie設定HTTP Only屬性即可,js無權訪問

而防禦CSRF,推薦使用token機制,伺服器頒發token,按規範來說推薦儲存在Session Storage中(也可以放cookie中,由於瀏覽器的同源策略,網站A無法訪問網站B的cookie),js將其新增到請求的引數或Header中

以上兩個措施,都需要做到,才能防護這兩個攻擊。

另外博主以為,現在伺服器校驗referer Header也是能防禦CSRF的



四、錯誤示範

  • 把使用者登入憑證放在Cookie中,未設定HTTP Only,請求中無token引數/Header

    容易遭受XSS、CSRF攻擊

  • 把使用者登入憑證放在Cookie中,設定了HTTP Only,請求中無token引數/Header

    容易遭受CSRF攻擊,成功防禦XSS攻擊

  • 把使用者登入憑證放在Cookie中,未設定HTTP Only,請求中有token引數/Header(前端把token儲存在Session Storage,儲存在Cookies,未設定HTTP Only)

    容易遭受XSS攻擊,攻擊者能構造請求,把token拼上,成功防禦CSRF攻擊

  • 把使用者登入憑證放在Cookie中,設定了HTTP Only,請求中有token引數/Header【規範防禦】

    成功防禦XSS、CSRF攻擊

  • 把使用者登入憑證放在Cookie中,未設定HTTP Only,請求中有token引數/Header(前端把token儲存在儲存在Cookies,設定了HTTP Only)【稀裡糊塗地防禦】

    成功防禦XSS、CSRF攻擊。但不可能,Cookie都未設定HTTP Only,token為啥會這麼巧設定了

  • 把使用者登入憑證放在Cookie中,設定了HTTP Only,且請求引數/Header中也新增並校驗此憑證【極簡防禦一】

    一個憑證同時防禦XSS、CSRF攻擊,雖然看起來不正道,不正經

  • 把使用者登入憑證放在Cookie中,設定了HTTP Only,且伺服器校驗referer Header【極簡防禦二】

    一個憑證同時防禦XSS、CSRF攻擊,瀏覽器js目前無法修改請求的referer頭,會提示Refused to set unsafe header "Referer"



五、最後

現在瀏覽器的安全也逐步做上來了,一定程度上能防禦CSRF,除了cookie samesite,跨域在POST請求前,還會傳送OPTIONS請求,如果OPTIONS請求不通過,無法POST

但開發還是要規範,不能指望使用者都是新瀏覽器

以上,講得不對望指正



相關文章