CSRF (Cross-Site Request Forgery) memanfaatkan session yang sudah login untuk mengeksekusi aksi tanpa sepengetahuan user. Contoh: user login ke bank.com, lalu mengunjungi evil.com yang diam-diam mengirim POST bank.com/transfer menggunakan cookie session yang masih aktif.
Kenapa ini bisa terjadi? Browser otomatis mengirim cookie untuk domain tujuan, termasuk dari request cross-site. Tanpa proteksi, server menerima request tersebut sebagai permintaan sah.
Tiga lapis pertahanan:
1. SameSite Cookie (proteksi dasar, nilai default modern):
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Lax
SameSite=Lax(default di browser baru) — cookie tidak dikirim untuk POST cross-siteSameSite=Strict— cookie tidak dikirim sama sekali untuk cross-siteSameSite=None— cookie dikirim semua, harus ditemaniSecure
2. CSRF Token (Synchronizer Token Pattern):
// Server mengeluarkan token per session dan menyimpannya
const csrfToken = crypto.randomBytes(32).toString("hex");
session.csrfToken = csrfToken;
// Form harus menyertakan token ini
// <input type="hidden" name="_csrf" value="${csrfToken}">
// Server memvalidasi saat mutation (POST/PUT/DELETE)
if (request.body._csrf !== session.csrfToken) {
return res.status(403).json({ error: "Invalid CSRF token" });
}
Token berbeda per session. Karena penyerang tidak bisa membaca cookie/session dari origin lain (Same-Origin Policy), mereka tidak bisa menebak token yang valid.
3. Double Submit Cookie (stateless alternative):
// Server mengirim token sebagai cookie DAN mengharapkan token yang sama di header
res.cookie("csrf-token", token, { sameSite: "strict" });
// Client membaca cookie dan mengirim ulang di header
fetch("/api/transfer", {
headers: { "X-CSRF-Token": readCookie("csrf-token") }
});
// Server membandingkan kedua nilai
if (req.cookies["csrf-token"] !== req.headers["x-csrf-token"]) {
return res.status(403).end();
}
Origin / Referer validation (safety net):
const trustedOrigins = ["https://myapp.com"];
if (!trustedOrigins.includes(req.headers.origin)) {
return res.status(403).end();
}
Kapan tidak perlu CSRF token?
- Endpoint stateless yang hanya bergantung pada
Authorization: Bearer <token>(bukan cookie). Browser tidak mengirim header Authorization secara otomatis, jadi CSRF tidak relevan. - Request GET yang murni membaca data (idempotent).
Kesalahan umum:
- Mengandalkan hanya SameSite — browser lama tidak mendukungnya
- Menyimpan CSRF token di localStorage (bisa dibaca XSS) — simpan di cookie atau in-memory
- Token yang sama untuk semua user — harus per-session