CSRF 與 SameSite
攻擊原理
使用者登入銀行後,不小心點擊了駭客的連結:
<img src="https://bank.com/transfer?to=hacker&amount=10000" />
瀏覽器會自動帶上銀行的 Cookie,如果銀行沒做 CSRF 防護,錢就被轉走了!
Vibe Prompt
「幫我在 Next.js API Route 中實作 CSRF Token 驗證。」
// lib/csrf.js
import { createHash, randomBytes } from 'crypto'
const SECRET = process.env.CSRF_SECRET || randomBytes(32).toString('hex')
export function generateCsrfToken(sessionId) {
const hash = createHash('sha256')
hash.update(`${sessionId}:${SECRET}`)
return hash.digest('hex')
}
export function validateCsrfToken(token, sessionId) {
const expected = generateCsrfToken(sessionId)
return token === expected
}
// app/api/transfer/route.js
import { validateCsrfToken } from '@/lib/csrf'
export async function POST(request) {
const body = await request.json()
const sessionId = request.cookies.get('session_id')?.value
if (!validateCsrfToken(body.csrf_token, sessionId)) {
return Response.json({ error: 'CSRF 驗證失敗' }, { status: 403 })
}
// 處理轉帳...
}
SameSite Cookie 設定
// 設定 Cookie 時加入 SameSite
response.cookies.set('session_id', token, {
httpOnly: true,
secure: true,
sameSite: 'strict', // 最嚴格:完全禁止跨站攜帶
maxAge: 60 * 60 * 24
})
關鍵要點
- ✅ OWASP Top 10 = Web 應用安全最具權威的風險列表
- ✅ SQL Injection:永遠使用參數化查詢,不要串接字串
- ✅ XSS:對使用者輸入進行轉義(Escape),使用 CSP Header
- ✅ CSRF:使用 SameSite Cookie + CSRF Token 雙重保護
- ✅ 安全是設計階段就要考慮的,不是上線前才補
OWASP Top 10 (2021)
| 排名 | 漏洞 | 說明 | |:----:|------|------| | A01 | 權限控制失效 | IDOR、越權 | | A02 | 加密機制失效 | 未加密敏感資料 | | A03 | 注入攻擊 | SQL、NoSQL、Command Injection | | A04 | 不安全設計 | 安全未在設計階段考慮 | | A05 | 安全配置錯誤 | 預設密碼、未關閉除錯模式 | | A06 | 脆弱元件 | 使用有已知漏洞的套件版本 | | A07 | 認證與身分管理失效 | 弱密碼、Session 固定 | | A08 | 資料完整性失效 | 不安全的反序列化 | | A09 | 日誌與監控不足 | 無法偵測攻擊 | | A10 | SSRF | 伺服器端請求偽造 |
CSRF:偽造跨站請求
CSRF(Cross-Site Request Forgery)讓攻擊者偽造受害者的身份發送請求——你登入銀行後不小心點開惡意網站,它偷偷發送 POST /transfer?amount=10000&to=attacker。
CSRF 的防護方式
| 防護 | 做法 | 效果 |
|:----|:----|:----|
| SameSite Cookie | Cookie 設 SameSite=Lax | 瀏覽器層級防護,現在預設啟用 |
| CSRF Token | 表單中嵌入隨機 Token | 需要在同一個頁面拿到 Token 才能發請求 |
| Referer/Origin 檢查 | 驗證請求來源 | 簡單但可以被繞過 |
SameSite Cookie 的三種模式
| 模式 | 跨站請求時 | 安全性 | 使用場景 |
|:----|:---------|:-----|:--------|
| None | 都會帶上 Cookie | ❌ | 第三方嵌入(如 iframe) |
| Lax | GET 請求會帶(連結、導航) | ✅ | 預設值,適合大多數網站 |
| Strict | 完全不帶 Cookie | ✅✅ | 銀行、金融網站 |
下一章預告:安全 API 實作
CSRF 是 Session-based 認證的風險。下一章整合前面所有知識——設計一個從認證到輸出都安全的 API。