Vẫn cần. SameSite=Lax thu hẹp rất nhiều bề mặt tấn công nhưng không phải là hàng rào đủ.
Lớp 1 — SameSite cookie. Lax chặn cookie đi kèm request cross-site trừ điều hướng top-level bằng GET. Chỗ hở:
- Nếu có endpoint đổi trạng thái bằng GET (/account/delete?id=5), Lax không cứu.
- Một số trình duyệt/webview cũ không áp mặc định Lax.
- Request từ subdomain bị chiếm vẫn là same-site (SameSite xét theo eTLD+1, không phải origin).
Lớp 2 — CSRF token. Server phát token gắn với phiên, form/AJAX gửi kèm trong body hoặc header tuỳ chỉnh; server so khớp. Biến thể double-submit cookie không cần lưu state nhưng yếu hơn nếu subdomain bị chiếm (kẻ tấn công ghi được cookie). Token đúng nghĩa phải gắn với session và không đoán được.
Lớp 3 — kiểm tra Origin / Sec-Fetch-Site. Với mọi request đổi trạng thái, so Origin với host của mình; thiếu Origin thì xét Referer. Rẻ và hiệu quả, nhưng cần cẩn thận với proxy làm mất header và với client không phải trình duyệt.
const origin = req.headers.origin
if (req.method !== 'GET' && origin && new URL(origin).host !== req.headers.host) {
return res.status(403).end()
}Hai lưu ý hay bị hỏi tiếp:
- API dùng Authorization: Bearer thay cookie thì miễn nhiễm CSRF, vì trình duyệt không tự gắn header đó.
- Nếu site có XSS thì mọi phòng thủ CSRF đều vô nghĩa — script cùng origin đọc được token. Sửa XSS trước.