2025年6月11日 星期三

PHP 的 session 與 cookie 有什麼不同?如何安全地管理它們?

 在 PHP 中,Session 和 Cookie 都是用於在網站上維持使用者狀態的機制,但它們在儲存位置、生命週期和安全性方面存在顯著差異。

PHP Session 與 Cookie 的不同

特性SessionCookie
儲存位置伺服器端(通常是檔案、資料庫或快取)用戶端(瀏覽器)
儲存內容大量資料,可以是任何 PHP 序列化後的數據少量文本資料(通常限制在 4KB 左右)
生命週期預設為瀏覽器關閉或達到設定的閒置時間(例如 30 分鐘)可以設定過期時間,從瀏覽器關閉到數年不等
安全性較高,數據儲存在伺服器端,使用者無法直接修改較低,數據儲存在用戶端,使用者可以查看甚至篡改
傳輸方式只傳輸 Session ID 給用戶端,數據在伺服器端處理數據直接從用戶端傳輸到伺服器端(HTTP Header)
用途用於儲存敏感或大量資料,例如登入狀態、購物車內容用於儲存使用者偏好、追蹤使用者行為、記住登入狀態

簡而言之:

  • Session 就像一個服務生在餐廳為你保留的「桌子」:你告訴服務生你想點的菜(資料),服務生會記住,並在你每次來的時候根據你的「號碼牌」(Session ID)知道你是誰。所有的菜(資料)都在廚房(伺服器)裡,你不能直接碰。
  • Cookie 就像你口袋裡的「便條紙」:你寫下你想記住的內容(資料),然後把它交給瀏覽器。每次瀏覽器發送請求時,都會把這張便條紙(Cookie)一起發送給伺服器。別人也能看到你便條紙上的內容。

如何安全地管理 Session 與 Cookie?

安全地管理 Session 和 Cookie 對於保護使用者數據和防止惡意攻擊至關重要。以下是一些關鍵的安全實踐:

Session 的安全管理:

  1. 使用 HTTPS/SSL: 始終在整個網站上使用 HTTPS 來加密所有流量。這可以防止 Session ID 在傳輸過程中被竊聽(例如透過中間人攻擊)。
  2. 重新生成 Session ID:
    • 登入後: 使用 session_regenerate_id(true); 在使用者成功登入後立即重新生成 Session ID。這可以防止 Session 固定攻擊 (Session Fixation Attack),即攻擊者在使用者登入前就設定一個 Session ID,然後在使用者登入後劫持該 Session。
    • 權限變更後: 每次使用者權限發生變化時(例如從普通使用者變為管理員),也應該重新生成 Session ID。
  3. 設定 Session 過期時間:
    • 閒置過期: 設定一個合理的閒置過期時間(例如 30 分鐘)。可以使用 session.gc_maxlifetimesession.cookie_lifetime 來控制。
    • 絕對過期: 為 Session 設定一個絕對過期時間,即使使用者一直在活動,也強迫他們在一定時間後重新登入。這可以透過在 Session 中儲存時間戳記來實現。
  4. 限制 Session Cookie 的屬性:
    • HttpOnly 將 Session Cookie 設定為 HttpOnly。這可以防止 JavaScript 存取 Cookie,從而降低跨站腳本攻擊 (XSS) 的風險,即使網頁存在 XSS 漏洞,攻擊者也難以竊取 Session ID。在 php.ini 中設定 session.cookie_httponly = 1 或使用 session_set_cookie_params()
    • Secure 將 Session Cookie 設定為 Secure。這確保 Cookie 只會透過 HTTPS 連線發送。在 php.ini 中設定 session.cookie_secure = 1 或使用 session_set_cookie_params()
    • SameSite 設定 SameSite 屬性(例如 LaxStrict)來防止跨站請求偽造 (CSRF) 攻擊。Strict 最安全,但可能會影響某些功能;Lax 是一個比較平衡的選擇。
  5. 不儲存敏感數據: 避免在 Session 中儲存極度敏感的數據,例如密碼或信用卡號。如果必須儲存,應進行加密。
  6. 定期清理 Session 數據: 確保伺服器上的舊 Session 數據被定期清理,以防止 Session 數據洩露或佔用過多儲存空間。PHP 的垃圾回收機制會自動處理,但可以調整 session.gc_probabilitysession.gc_divisor
  7. 監控異常活動: 實作機制來監控異常的 Session 活動,例如來自不同 IP 地址的相同 Session ID 請求,這可能表明 Session 劫持。

Cookie 的安全管理:

  1. 使用 HTTPS/SSL: 與 Session 相同,所有發送 Cookie 的請求都必須透過 HTTPS。
  2. 設定 HttpOnly 屬性: 對於任何不希望被 JavaScript 存取的 Cookie,都應該設定 HttpOnly 屬性,防止 XSS 攻擊竊取 Cookie。
    PHP
    setcookie("name", "value", [
        'expires' => time() + 3600,
        'path' => '/',
        'domain' => 'yourdomain.com',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Lax' // 或 'Strict'
    ]);
    
  3. 設定 Secure 屬性: 確保 Cookie 只透過 HTTPS 發送。
  4. 設定 SameSite 屬性:
    • SameSite=Lax 在跨站請求中,只有在頂級導航(例如點擊連結)時才會發送 Cookie,對於非 GET 請求(如 POST)則不發送。這是大多數情況下的良好平衡。
    • SameSite=Strict Cookie 只有在同站請求中才會發送。這對 CSRF 防護最嚴格,但可能會影響需要跨站發送 Cookie 的特定功能。
    • 不設定 SameSite (預設 None): 最不安全,容易受到 CSRF 攻擊。如果必須跨站點發送 Cookie,則必須同時設定 Secure
  5. 設定合理的過期時間: 根據 Cookie 的用途設定合適的過期時間。對於「記住我」功能,可以設定較長的過期時間,但要確保儲存的不是敏感數據。
  6. 加密或雜湊敏感數據: 如果 Cookie 必須包含任何敏感數據(雖然不推薦),則應該對其進行加密或雜湊處理,以便即使 Cookie 被竊取,攻擊者也難以利用。
  7. 避免在 Cookie 中儲存敏感數據: 盡量不要在 Cookie 中儲存用戶名、密碼、信用卡號等敏感資訊。這些資訊應該儲存在伺服器端(例如 Session 中),並透過 Session ID 來識別。
  8. 驗證 Cookie 數據: 永遠不要信任來自 Cookie 的數據。在伺服器端對所有從 Cookie 讀取的數據進行驗證和清理,以防止注入攻擊。
  9. 使用短期的、隨機的 Cookie 值: 對於用於追蹤的非敏感 Cookie,使用隨機生成且不包含任何用戶可識別信息的短期值。

透過結合這些 Session 和 Cookie 的安全管理策略,可以顯著提高 PHP 應用程式的安全性,保護使用者免受常見的 Web 攻擊。

沒有留言:

張貼留言

網誌存檔