第 1 章:導讀
Web 框架不分安全與否,關鍵在正確使用。Rails 提供許多聰明 Helper(如參數化查詢防 SQL 注入)。Gartner 統計:75% 攻擊針對 Web 應用,97% 受測應用存在漏洞。威脅:帳號劫持、繞過權限、敏感資料洩露、釣魚、惡意軟體分發、品牌受損。本指南涵蓋 Session、CSRF、重定向/檔案、大量賦值、用戶管理、注入攻擊六大主題。
第 2 章:Session 深度解析
2.1 什麼是 Session
HTTP 無狀態,Session 賦予狀態。Rails 自動管理:新用戶建立 Session,舊用戶載入現有 Session。session[:user_id] = @current_user.id,User.find(session[:user_id])。
2.2 Session ID
32 位元組 MD5 雜湊:當前時間 + rand(0..1) + Process.pid + 常數字串 → Digest::MD5.hexdigest。
2.3 Session 劫持
竊取 Session ID → 冒用身份。途徑與對策:
| 途徑 | 對策 |
| 非加密網路嗅探(公共 Wi-Fi) | 全站 HTTPS |
| 公用電腦未登出/清除 Cookie | 明顯登出按鈕、短 Session 逾時 |
| XSS 竊取 Cookie | HttpOnly Cookie、XSS 徹底防護 |
| Session 固定攻擊 | 登入後重新產生 Session ID |
黑市行情:銀行帳號 $10-$1000、信用卡 $0.4-$20、拍賣帳號 $1-$8、Email 密碼 $4-$30(Symantec 報導)。
2.4 Session 存儲最佳實踐
- 勿存大物件:存 ID,實體存資料庫,避免同步問題與儲存空間浪費
- 勿存關鍵資料:用戶清除 Cookie/關閉瀏覽器即丟失;Client-side 存儲用戶可讀取
2.5 Session 存儲機制對比
| 機制 | 特點 | 安全考量 |
| ActiveRecordStore | 資料庫表儲存 ID+Hash,每請求讀寫,生產環境首選 | 資料不外洩,效能可接受 |
| CookieStore (Rails 2+) | Hash 直接存在 Cookie(Base64),無 Session ID,速度極快 | 1. 4KB 上限 2. 用戶可見內容(無機密) 3. 依賴 Secret 簽名防竄改(SHA512,≥30 字元隨機字串) |
# config/environment.rb
config.action_controller.session = {
:session_key => '_app_session',
:secret => '0x0dkfj3927dkc7djdh36rkckdfzsg...' # 極長隨機字串
}
加密 CookieStore 變體可隱藏內容。
2.6 CookieStore 重放攻擊
場景:用戶餘額存 Session → 消費 → 餘額減少 → 攻擊者覆蓋舊 Cookie → 餘額復原。
對策:敏感資料存資料庫,Session 僅存用戶 ID。或加入 nonce(一次性隨機數),但多伺服器部署複雜。
2.7 Session 固定攻擊
- 攻擊者訪問目標站 → 取得有效 Session ID
- 定期訪問保持 Session 存活
- XSS 注入
document.cookie="_session_id=ATTACKER_ID" 強制受害者使用
- 受害者登入 → 雙方共享同一 Session
2.8 Session 固定防禦
# SessionsController#create
reset_session # 登入成功後重新產生 Session ID,舊 ID 失效
或每請求驗證用戶屬性(真實 IP、User-Agent),不匹配拒絕存取。
2.9 Session 過期管理
永不過期 = 攻擊窗口無限大。伺服端強制過期:
class Session < ActiveRecord::Base
def self.sweep(time_ago = nil)
time = case time_ago
when /^(\d+)m$/ then Time.now - $1.to_i.minutes
when /^(\d+)h$/ then Time.now - $1.to_i.hours
when /^(\d+)d$/ then Time.now - $1.to_i.days
else Time.now - 1.hour
end
# 僅清理更新時間過舊
delete_all ["updated_at < ?", time]
# 進階:同時清理建立時間過舊(防攻擊者定期喚醒)
# delete_all ["updated_at < ? OR created_at < ?", time, 2.days.ago]
end
end
定期排程執行 Session.sweep("20m")。
- 上一篇文章: Rails 安全指南(二):CSRF 跨站請求偽造原理與防禦
- 下一篇文章: 使用 SIP Servlet 為 Java EE 應用程式添加語音通訊功能
Copyright ©
程式碼之家 All Rights Reserved