📅 Mei 2026 ⏱ 8 menit baca🔒 Security Engineering
1. Ilusi Keamanan di Balik Tombol 'Login'
Mengapa CSRF Lebih Berbahaya dari yang Kamu Bayangkan

Bayangkan kamu sedang login di aplikasi perbankan online. Semua terlihat aman — koneksinya HTTPS, password-mu kuat, dan kamu tidak pernah membagikan kredensial ke siapapun. Tapi tanpa sadar, saat kamu membuka tab baru dan mengunjungi sebuah situs yang tampak biasa, uangmu berpindah ke rekening orang asing.
Inilah Cross-Site Request Forgery (CSRF) — serangan yang bekerja diam-diam dengan memanfaatkan kepercayaan yang sudah diberikan browser kepada server. Yang menakutkan: penyerang tidak perlu mencuri password-mu. Mereka cukup "meminjam" sesi autentikasi yang sudah ada.
Dampaknya bisa sangat nyata. Dalam konteks perbankan, satu request CSRF yang berhasil bisa memindahkan dana tanpa sepengetahuan korban. Dalam aplikasi enterprise, serangan ini bisa mengubah hak akses pengguna, menghapus data penting, atau bahkan mengambil alih akun admin — semua tanpa meninggalkan jejak kredensial yang mencurigakan di log server.
"CSRF mengeksploitasi kepercayaan yang dimiliki sebuah situs web terhadap browser pengguna — bukan sebaliknya."
⚠ Fakta PentingCSRF masuk dalam daftar OWASP Top 10 selama lebih dari satu dekade. Meskipun sudah banyak framework yang mengimplementasikan proteksi otomatis, implementasi yang keliru atau sesi yang tidak dikelola dengan baik masih menjadi celah nyata di produksi.
2. Mekanisme Serangan CSRF Langkah demi Langkah
CSRF bekerja karena browser secara otomatis menyertakan cookie — termasuk session cookie — dalam setiap request ke domain yang bersangkutan. Penyerang memanfaatkan perilaku ini untuk memicu aksi atas nama korban.
Prasyarat Serangan
Agar CSRF berhasil, tiga kondisi ini harus terpenuhi secara bersamaan:
- Korban sudah login dan memiliki sesi aktif di aplikasi target (misalnya bank, e-commerce, atau panel admin).
- Aplikasi target menggunakan cookie-based authentication tanpa proteksi CSRF yang memadai.
- Penyerang bisa memprediksi atau mengetahui parameter yang dibutuhkan untuk melakukan aksi berbahaya tersebut.
Alur Serangan (Attack Flow Diagram)


Contoh Payload CSRF
Ada tiga varian umum serangan CSRF yang sering digunakan:
Varian 1 — Image Tag (GET request):
<!-- Dimuat secara otomatis saat halaman dibuka -->
<img src="https://bank.com/transfer?to=hacker&amount=5000000"
width="0" height="0" style="display:none">
HTMLVarian 2 — Auto-submit Form (POST request):
<form id="csrf-form" action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="hacker">
<input type="hidden" name="amount" value="5000000">
</form>
<script>document.getElementById('csrf-form').submit();</script>
HTMLVarian 3 — CSRF via Fetch API / XMLHttpRequest (JSON API):
Varian ini menarget REST API modern yang menerima Content-Type: application/json. Meski browser memblokir cross-origin fetch secara default via CORS, penyerang bisa memanfaatkan endpoint yang salah konfigurasi Access-Control-Allow-Origin: *, atau mengirim request dengan content-type sederhana yang tidak memicu preflight.
3. Kerentanan Session Management yang Memperparah CSRF
CSRF tidak bekerja sendirian. Efektivitasnya sangat bergantung pada bagaimana aplikasi mengelola sesi pengguna. Session yang buruk adalah bahan bakar yang membuat CSRF semakin berbahaya.
Session Fixation
Penyerang menanamkan Session ID yang sudah diketahui ke browser korban sebelum login. Caranya bisa bermacam-macam: via URL parameter, subdomain yang dikendalikan penyerang, atau injeksi cookie langsung. Saat korban login, jika server tidak melakukan regenerasi Session ID, penyerang yang sudah mengetahui Session ID tersebut kini memiliki akses penuh ke sesi aktif korban — kombinasi mematikan ketika digabungkan dengan teknik CSRF.
Session yang Tidak Pernah Expire
Sesi tanpa timeout membuka jendela serangan yang tidak terbatas. Pengguna yang lupa logout di komputer publik atau warnet meninggalkan sesi aktif selama berjam-jam bahkan berhari-hari. Ini peluang sempurna bagi penyerang — mereka hanya perlu menunggu korban mengunjungi halaman berbahaya kapan pun selama sesi masih hidup.
Cookie Tanpa Atribut Keamanan
# Konfigurasi BURUK — rentan terhadap CSRF dan XSS
Set-Cookie: sessionId=abc123
# Tidak ada HttpOnly → bisa dicuri via XSS
# Tidak ada Secure → bisa dicuri via HTTP sniffing
# Tidak ada SameSite → rentan CSRF!
HTTP🔍 Perhatikan Session ID yang dapat diprediksi (sequential, timestamp-based, atau entropi rendah) memudahkan penyerang melakukan session hijacking yang kemudian dikombinasikan dengan CSRF untuk dampak maksimal.SRF Token, SameSite Cookie, dan Validasi Header
Tambahan: Kenali Juga Risiko IDOR (OWASP A01:2021)
Selain CSRF, ada risiko Insecure Direct Object Reference (IDOR) yang masuk dalam kategori Broken Access Control di OWASP Top 10 2021. IDOR terjadi ketika aplikasi menerima input ID objek langsung dari user tanpa memverifikasi otorisasi kepemilikannya.
- Skenario Serangan: Penyerang mengubah parameter ID invoice pada URL dari
targetapp.com/api/invoice?id=10042menjadiid=10041. Karena server abai melakukan cek otorisasi, data sensitif korban otomatis bocor.
Pseudocode Kerentanan vs Mitigasi:
JavaScript
// ❌ RENTAN: Langsung query tanpa cek kepemilikan
app.get('/api/invoice', async (req, res) => {
const invoice = await db.findInvoiceById(req.query.id);
return res.json(invoice);
});
// ✅ AMAN: Validasi kepemilikan objek via session server
app.get('/api/invoice', requireAuth, async (req, res) => {
const invoice = await db.findInvoiceById(req.query.id);
if (invoice.userId !== req.session.userId) {
return res.status(403).json({ message: 'Akses Ditolak!' });
}
return res.json(invoice);
});(Tips: Gunakan UUID v4 alih-alih ID angka berurutan agar parameter mustahil ditebak penyerang).
4. Mitigasi: CSRF Token, SameSite Cookie, dan Validasi Header
A. CSRF Token (Synchronizer Token Pattern)
Pendekatan ini menyisipkan nilai rahasia unik yang harus disertakan dalam setiap state-changing request. Penyerang tidak bisa memprediksi atau membaca token ini karena Same-Origin Policy.
# Server: Generate token saat session dibuat
csrf_token = secrets.token_hex(32)
session['csrf_token'] = csrf_token
# Di HTML form:
<input type="hidden" name="csrf_token"
value="{{ csrf_token }}">
# Server: Validasi pada setiap POST/PUT/DELETE
if request.form['csrf_token'] != session['csrf_token']:
abort(403)
PythonB. SameSite Cookie Attribute
Cara paling elegan dan modern untuk mencegah CSRF — cukup tambahkan satu atribut pada cookie. Browser akan menolak mengirim cookie ke request lintas-situs.
# Strict: Cookie TIDAK dikirim untuk request cross-site apapun
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure; HttpOnly
# Lax: Cookie dikirim hanya untuk navigasi top-level (klik link)
# Direkomendasikan untuk sebagian besar aplikasi
Set-Cookie: sessionId=abc123; SameSite=Lax; Secure; HttpOnly
# None: Cookie dikirim untuk semua request (perlu Secure!)
Set-Cookie: sessionId=abc123; SameSite=None; Secure
HTTPC. Validasi Origin dan Referer Header
Server dapat memverifikasi asal request dengan membandingkan header Origin atau Referer dengan whitelist domain yang diizinkan.
def validate_csrf_origin(request):
allowed_origins = ['https://yourdomain.com', 'https://www.yourdomain.com']
origin = request.headers.get('Origin') or \
request.headers.get('Referer')
if not origin or not any(origin.startswith(o) for o in allowed_origins):
raise PermissionDenied("CSRF check failed")
Python💡 Best Practice Gunakan kombinasi SameSite=Lax + CSRF Token untuk perlindungan berlapis. SameSite melindungi dari sebagian besar serangan CSRF otomatis, sementara CSRF token menjadi safety net untuk kasus edge case seperti subdomain attacks.
Arsitektur Memperngaruhi Mitigasi: Web Tradisional vs REST API
Strategi penanganan CSRF sangat bergantung pada arsitektur aplikasi Anda
Aplikasi Web Tradisional (Stateful): Menggunakan Session-Cookie. Browser otomatis mengirimkan cookie sesi pada tiap request, membuat arsitektur ini sangat rentan CSRF.
- Mitigasi: Wajib menyisipkan CSRF Token pada setiap form HTML (
POST/PUT/DELETE) dan mengaktifkan atributSameSite=Lax/Strictpada cookie.
REST API Modern (Stateless): Menggunakan token seperti JWT (JSON Web Token). Token ini umumnya disimpan di localStorage atau memori aplikasi.
- Mitigasi: Client wajib mengirimkan token melalui header kustom (misal:
Authorization: Bearer <JWT>). Karena browser tidak mengirimkan header kustom secara otomatis pada cross-origin request, REST API secara alami kebal dari CSRF tradisional.
Catatan Kritis: Jika Anda terpaksa menyimpan JWT di dalam Cookie (untuk mencegah XSS), REST API Anda akan kembali rentan terhadap CSRF. Jika ini terjadi, Anda tetap wajib menerapkan mitigasi CSRF tradisional seperti teknik Double Submit Cookie.
5. Implementasi Secure Session Management
Regenerasi Session ID Setelah Login
Session ID harus diperbarui segera setelah proses autentikasi berhasil. Ini mencegah Session Fixation attack — di mana penyerang yang mengetahui Session ID sebelum login tidak bisa menggunakannya setelah login.
// Node.js dengan express-session
app.post('/login', async (req, res) => {
const user = await authenticateUser(req.body);
if (user) {
// ✅ Regenerate session ID setelah login berhasil
req.session.regenerate((err) => {
req.session.userId = user.id;
req.session.csrfToken = crypto.randomBytes(32).toString('hex');
res.json({ success: true });
});
}
});
JavaScriptTimeout dan Idle Session
# Django settings.py — konfigurasi session yang aman
# Absolute timeout: 8 jam
SESSION_COOKIE_AGE = 28800
# Idle timeout: hapus session jika browser ditutup
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# Atribut keamanan cookie
SESSION_COOKIE_SECURE = True # Hanya HTTPS
SESSION_COOKIE_HTTPONLY = True # Tidak bisa diakses JS
SESSION_COOKIE_SAMESITE = 'Lax' # Proteksi CSRF
PythonChecklist Secure Session Management
✅ Checklist
① Session ID harus panjang (≥128 bit), acak, dan tidak dapat diprediksi ② Regenerasi Session ID setelah login, logout, dan perubahan privilege ③ Implementasi absolute timeout (8–24 jam) dan idle timeout (15–30 menit) ④ Selalu set cookie dengan flag: Secure, HttpOnly, SameSite=Lax ⑤ Hapus session dari server saat logout (tidak hanya menghapus cookie) ⑥ Pertimbangkan session binding ke IP/User-Agent untuk aplikasi kritis
6. Studi Komparatif: Laravel vs Django vs Spring
Framework modern sudah menyediakan proteksi CSRF bawaan, tapi pendekatannya berbeda. Memahami perbedaan ini penting agar kita tidak menonaktifkan fitur keamanan tanpa sadar.

Contoh: CSRF di Laravel untuk AJAX
// Tambahkan CSRF token ke semua AJAX request via Axios
import axios from 'axios';
// Laravel menyimpan token di meta tag
axios.defaults.headers.common['X-CSRF-TOKEN'] =
document.querySelector('meta[name="csrf-token"]').getAttribute('content');
// Atau gunakan Sanctum untuk SPA authentication
await axios.get('/sanctum/csrf-cookie');
JavaScriptContoh: CSRF di Django untuk AJAX
# Ambil CSRF token dari cookie, sertakan di header request
function getCookie(name) {
let cookieValue = null;
if (document.cookie) {
document.cookie.split(';').forEach(cookie => {
const [k, v] = cookie.trim().split('=');
if (k === name) cookieValue = decodeURIComponent(v);
});
}
return cookieValue;
}
fetch('/api/transfer/', {
method: 'POST',
headers: { 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({ amount: 100, to: 'friend@email.com' })
});
JavaScriptKesimpulan
CSRF adalah serangan yang berbahaya justru karena sifatnya yang tidak terlihat — tidak ada malware yang diinstall, tidak ada password yang dicuri. Penyerang hanya perlu membuat korban yang sudah terautentikasi mengunjungi halaman yang tepat, dan browser akan melakukan "kejahatan" itu atas nama korban secara otomatis. Inilah yang membuat CSRF tetap relevan bahkan di era framework modern yang serba otomatis.
Kombinasi pertahanan yang efektif untuk 2024 ke depan adalah:
- SameSite=Lax sebagai lapisan pertama — mencegah hampir semua CSRF otomatis dengan satu baris konfigurasi.
- CSRF Token sebagai lapisan kedua — safety net untuk edge cases, wajib untuk operasi finansial dan perubahan data kritis.
- Secure Session Management — regenerasi ID, timeout yang tepat, dan atribut cookie yang benar sebagai fondasi keseluruhan.
- Validasi Origin/Referer sebagai lapisan ketiga — untuk aplikasi dengan keamanan tinggi seperti perbankan.
Framework modern seperti Laravel, Django, dan Spring sudah menyediakan semua ini secara built-in. Tugas kita sebagai developer adalah memastikan kita tidak mematikan fitur keamanan tersebut tanpa alasan yang jelas — dan jika harus dikecualikan (misalnya untuk REST API), pastikan ada proteksi alternatif seperti JWT atau OAuth2.
Keamanan terbaik adalah keamanan yang tidak mengharuskan penggunamu berpikir tentang keamanan.
Referensi
- OWASP Foundation. (2023). Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet. owasp.org
- OWASP Foundation. (2021). OWASP Top 10 2021 — A01:2021-Broken Access Control. owasp.org/Top10/
- Mozilla Developer Network. (2024). Set-Cookie: SameSite attribute. developer.mozilla.org
- Barth, A., Jackson, C., & Mitchell, J. C. (2008). Robust Defenses for Cross-Site Request Forgery. ACM Conference on Computer and Communications Security (CCS).
- Django Project. (2024). Cross Site Request Forgery protection. docs.djangoproject.com
- Spring Security Team. (2024). Cross Site Request Forgery (CSRF). Spring Security Reference. spring.io
- West, M. (2016). SameSite Cookies Explained. web.dev. web.dev