Session Hijacking#

概述#

當網站成功驗證使用者身份後,瀏覽器與伺服器之間會開啟一個 session(會話)。Session 是一段 HTTP 對話,瀏覽器發送一系列對應使用者操作的 HTTP 請求,而伺服器能辨識這些請求來自同一個已驗證的使用者,無需每次都重新登入。

如果攻擊者能存取或偽造瀏覽器發送的 session 資訊,就能存取任何使用者的帳號。這就是 session hijacking(會話劫持)。

Session hijacking 的風險通常比認證漏洞更大,因為它允許攻擊者存取任何使用者的帳號。

Session 的運作原理#

Session Identifier#

當使用者透過 HTTP 進行身份驗證時,伺服器會在登入過程中分配一個 session identifier(session ID)

  • Session ID 通常是一個大型的隨機產生數字
  • 它是瀏覽器在每個後續 HTTP 請求中需要傳送的最少資訊
  • 伺服器辨識每個請求中的 session ID,將其對應到適當的使用者,並代為執行操作

Session ID 必須是與使用者名稱不同的臨時指派值。如果瀏覽器直接使用使用者名稱作為 session ID,駭客就能假冒任何他們想要的使用者。

除了使用者名稱外,伺服器通常還會儲存其他 session state(會話狀態),包含使用者近期活動的相關資訊,例如瀏覽過的頁面清單或購物車中的商品。

Server-Side Sessions#

在傳統模式中,伺服器將 session state 保存在記憶體中,瀏覽器和伺服器之間只傳遞 session identifier。

  • 歷史上,伺服器嘗試過多種方式傳輸 session ID:URL 中、HTTP header 中、HTTP 請求的 body 中
  • 目前社群共識是使用 session cookies 來傳送 session ID
  • 伺服器在 HTTP response 的 Set-Cookie header 中回傳 session ID,瀏覽器則在後續請求的 Cookie header 中附上相同資訊

優點:

  • 廣泛實作且通常非常安全

缺點:

  • 有可擴展性限制,因為伺服器必須將 session state 儲存在記憶體中
  • 在多伺服器環境中,只有一台伺服器知道該 session,需要透過共享快取或資料庫來同步
  • 每個使用者都會增加 session store 的負擔

Client-Side Sessions#

為了解決 server-side sessions 的擴展性問題,client-side sessions 將所有 session state 放在 cookie 中傳回客戶端:

  • 伺服器將 session state 序列化為文字(通常是 JSON),設定在 HTTP header 中
  • 每台伺服器都有重建 session 所需的一切資訊,不需要共享狀態
  • 非常適合擴展到數千名同時在線的使用者

Client-side sessions 存在明顯的安全問題。在簡單的實作中,惡意使用者可以輕易操縱或偽造 session cookie 的內容。

保護 client-side session cookies 的方法:

  1. 加密(Encryption):在發送前加密序列化的 cookie,伺服器在收到時解密。任何操縱或偽造的嘗試都會破壞編碼的 session,使 cookie 無法讀取
  2. 數位簽章(Digital Signature):為 cookie 加上唯一的「指紋」,伺服器可以偵測到 session state 被竄改的嘗試,因為簽章值會不同

簽章 cookie 而非加密仍允許使用者在瀏覽器 debugger 中讀取 session 資料。如果你儲存了追蹤資訊等不希望使用者看到的資料,應使用加密。

攻擊者如何劫持 Session#

攻擊者使用三種主要方法劫持 session:cookie theft(cookie 竊取)、session fixation(session 固定)、以及利用弱 session ID

攻擊者通常透過竊取已驗證使用者的 Cookie header 值來實現 session hijacking。竊取 cookie 的三種技術:

  1. Cross-site scripting (XSS):注入惡意 JavaScript 讀取使用者的 cookie
  2. Man-in-the-middle attack:攔截網路流量中的 HTTP header
  3. Cross-site request forgery (CSRF):觸發未授權的 HTTP 請求

現代瀏覽器提供簡單的安全措施,可以透過在 Set-Cookie header 中加入關鍵字來防護:

Set-Cookie: session_id=278283910977381992837; HttpOnly; Secure; SameSite=Lax

攻擊者利用 XSS 注入 JavaScript 到使用者的瀏覽器中讀取 cookie,並發送到攻擊者控制的外部伺服器。

防護方式: 將所有 cookie 標記為 HttpOnly,告訴瀏覽器不要讓 JavaScript 程式碼存取 cookie。

Set-Cookie: session_id=278283910977381992837; HttpOnly

幾乎沒有正當理由需要讓 client-side JavaScript 存取 cookie,因此使用 HttpOnly 幾乎沒有缺點。

防護 Man-in-the-Middle Attack#

攻擊者透過中間人攻擊坐在瀏覽器和伺服器之間,讀取來回傳遞的網路流量。

防護方式:

  • 使用 HTTPS
  • 將 cookie 標記為 Secure,讓瀏覽器知道不要透過未加密的 HTTP 傳送 cookie
Set-Cookie: session_id=278283910977381992837; Secure

防護 Cross-Site Request Forgery#

使用 CSRF 的攻擊者不需要取得使用者的 session cookie,只需誘騙受害者點擊連結,瀏覽器就會自動帶上 session cookie。

防護方式: 使用 SameSite 屬性,指示瀏覽器僅在來自你的網站的 HTTP 請求中發送 session cookie:

  • SameSite=Strict:從所有外部網站的請求中移除 cookie(缺點:從社群媒體點擊連結進入需要重新登入)
  • SameSite=Lax:僅在 GET 請求時附帶 cookie,其他請求類型(POST、PUT、DELETE)則移除 cookie
Set-Cookie: session_id=278283910977381992837; SameSite=Lax

SameSite=Lax 通常是最佳選擇,因為網站通常透過 POST、PUT 或 DELETE 請求執行敏感操作,攻擊者無法誘騙受害者執行這些類型的敏感動作。

Session Fixation(Session 固定)#

在網際網路早期,許多瀏覽器不支援 cookie,因此伺服器使用 URL rewriting 將 session ID 附加到每個 URL 的結尾:

http://www.example.com/catalog/index.html;jsessionid=1234

URL rewriting 帶來兩個主要安全問題:

  1. Session ID 洩漏到 log 檔:存取 log 的攻擊者可以劫持使用者的 session
  2. Session fixation 攻擊:攻擊者預先設定 session ID,然後發送含有該 session ID 的連結給受害者

Session fixation 的攻擊流程:攻擊者預先固定 session ID,透過電子郵件或評論區發送誘人的連結。受害者點擊連結後進行身份驗證,該虛擬 session ID 就變成了真實的 session ID,攻擊者因此可以劫持該 session。

防護方式: 如果你的伺服器支援 URL rewriting 作為 session 追蹤方式,應透過設定停用它。例如 Apache Tomcat 7.0:

<session-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

利用弱 Session ID#

攻擊者也可以透過暴力猜測 session ID 來劫持 session:

  • Session ID 通常只是數字,如果這些數字夠小或可預測,攻擊者可以列舉潛在的 session ID 並逐一測試
  • 真正的隨機數在軟體中很難產生。大多數隨機數產生演算法使用環境因素(如系統時鐘時間)作為 seed
  • 如果攻擊者能確定足夠多的 seed 值,就能列舉潛在有效的 session ID

早期版本的 Apache Tomcat 伺服器就曾被發現存在此類漏洞。研究人員發現其隨機 session ID 產生演算法的 seed 是系統時間和記憶體物件的 hashcode,能夠可靠地猜出 session ID。

防護方式:

  • 查閱你的伺服器文件,確保它使用由強隨機數產生演算法生成的大型 session ID
  • 持續關注安全公告,及時修補 web stack 中的漏洞

總結#

  • Session state 可以儲存在 server side,或以加密或數位簽章的 cookie 儲存在 client side
  • 攻擊者會嘗試竊取 session cookies,應使用 HttpOnlySecureSameSite 關鍵字保護
  • 舊版伺服器可能容易受到 session fixation 攻擊,應停用 URL rewriting
  • 伺服器偶爾被發現使用可猜測的 session ID,應關注安全公告並及時修補