HTTP Security Headers yang Wajib Kamu Pasang — Perlindungan Pertama Sebelum Exploit Datang
Ada kalanya aku merasa website yang sudah dibuat dengan susah payah bagai rumah baru: fondasi kokoh, cat bagus, furniture rapi. Tapi lupa memasang kunci pintu. Bukan berarti rumahnya jelek, tapi satu celah kecil sudah cukup buat orang yang tidak bertanggung jawab masuk. Di dunia web, celah semacam itu sering kali bukan karena kode bisnis yang rumit, melainkan karena HTTP security headers yang belum diatur dengan benar.
Dulu aku pikir keamanan website cukup soal password kuat dan update CMS rutin. Ternyata, browser modern punya mekanisme pertahanan tambahan yang bisa kita aktifkan hanya dengan beberapa baris konfigurasi di server. Baris-baris itu bernama HTTP security headers. Mereka tidak mengubah tampilan, tidak memperlambat loading, tapi bisa membuat perbedaan besar saat ada yang mencoba mengeksploitasi aplikasimu.
Apa Itu HTTP Security Headers?
Setiap kali browser meminta halaman web, server mengirim balasan berupa HTTP response headers. Selain informasi seperti Content-Type dan Content-Length, header juga bisa berisi instruksi keamanan. Instruksi ini memberi tahu browser, "Hei, jangan lakukan ini," atau "Selalu lakukan itu."
Analoginya seperti aturan rumah tangga yang kita tempel di kulkas. Anak-anak tetap bisa masak, tapi mereka tahu batasan yang tidak boleh dilanggar. Begitu pula browser: header keamanan tidak membatasi fungsi website, hanya memberi batasan perilaku yang berisiko.
Yang menarik, banyak serangan web klasik seperti clickjacking, cross-site scripting (XSS), dan man-in-the-middle bisa dimitigasi sebagian besar hanya dengan header yang tepat. Tentu saja header bukan peluru ajaib, tapi mereka adalah lapisan pertahanan pertama yang murah dan efektif.
Header-Header Esensial yang Wajib Kamu Kenali
1. Strict-Transport-Security (HSTS)
Bayangkan kamu memesan ojek online dan drivernya menawarkan, "Mau lewat jalan tikus aja? Lebih cepat." Kamu tentu menolak karena tidak tahu apa yang menunggu di sana. HSTS bekerja dengan cara yang serupa: dia memberi tahu browser, "Website ini hanya boleh diakses lewat HTTPS. Jangan pernah coba-coba versi HTTP."
HSTS mencegah SSL stripping attack, di mana penyerang memaksa koneksi turun dari HTTPS ke HTTP. Setelah browser menerima header ini, dia akan selalu mengakses domainmu lewat HTTPS selama periode yang kamu tentukan.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
max-age=31536000 berarti browser menyimpan aturan selama satu tahun. includeSubDomains memastikan aturan berlaku untuk semua subdomain. Sementara preload adalah opsional tambahan jika kamu ingin mendaftarkan domain ke HSTS preload list milik Chrome.
2. Content-Security-Policy (CSP)
CSP adalah header paling powerful sekaligus paling tricky. Dia seperti daftar tamu eksklusif di sebuah pesta: hanya sumber yang terdaftar yang boleh membawa script, gambar, stylesheet, atau sumber daya lain ke halamanmu. Jika ada script jahat yang mencoba masuk dari domain liar, browser akan menolaknya.
Serangan XSS sering terjadi karena penyerang berhasil menyisipkan script ke halamanmu. Dengan CSP yang ketat, bahkan jika script itu masuk, browser tidak akan mengeksekusinya karena sumbernya tidak ada dalam daftar yang diizinkan.
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; frame-ancestors 'none';" always;
Konfigurasi di atas mengizinkan script hanya dari domain sendiri dan CDN tertentu, gambar dari domain sendiri beserta data URI, serta melarang halamanmu dibungkus dalam iframe. Untuk awalan, kamu bisa pakai mode Content-Security-Policy-Report-Only agar browser melaporkan pelanggaran tanpa memblokir apa pun. Setelah yakin, baru beralih ke header CSP yang sebenarnya.
3. X-Frame-Options
Header ini secara spesifik melindungi dari clickjacking. Serangan tersebut menyembunyikan tombol asli di balik elemen palsu dalam iframe, sehingga pengguna mengklik sesuatu yang sebenarnya tidak mereka maksud. X-Frame-Options memberi tahu browser apakah halaman boleh ditampilkan dalam frame.
add_header X-Frame-Options "SAMEORIGIN" always;
Nilai SAMEORIGIN mengizinkan framing hanya dari domain yang sama. Jika kamu tidak pernah menampilkan halaman dalam iframe, gunakan DENY. Meskipun CSP frame-ancestors sudah lebih modern, X-Frame-Options tetap berguna sebagai lapisan cadangan untuk browser lama.
4. X-Content-Type-Options
Browser kadang ceroboh. Jika server mengirim file tanpa Content-Type yang jelas, browser bisa menebak sendiri dan mengeksekusi file sebagai sesuatu yang berbahaya. Header ini mematikan perilaku menebak tersebut.
add_header X-Content-Type-Options "nosniff" always;
Dengan nosniff, browser akan memperlakukan file sesuai dengan tipe yang dideklarasikan server. File yang seharusnya statis tidak akan tiba-tiba dieksekusi sebagai script.
5. Referrer-Policy
Ketika pengguna mengklik tautan dari websitemu menuju situs lain, browser biasanya mengirim informasi asal pengunjung melalui header Referer. Informasi ini bisa membocorkan URL sensitif atau parameter query yang seharusnya tidak diketahui pihak ketiga.
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Nilai di atas mengirim origin saja saat navigasi lintas domain, tapi tetap mengirim URL lengkap untuk navigasi internal. Pilihan lain seperti no-referrer lebih ketat jika privasi adalah prioritas utama.
6. Permissions-Policy
Header ini dulu bernama Feature-Policy. Dia mengontrol fitur browser apa yang boleh digunakan oleh halamanmu dan konten pihak ketiga di dalamnya. Misalnya, kamu bisa mematikan akses kamera, mikrofon, geolokasi, atau akselerometer secara default.
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), accelerometer=()" always;
Ini berguna terutama saat website-mu menampilkan konten dari pihak ketiga yang tidak kamu kendalikan. Daripada mempercayai mereka tidak menyalahgunakan fitur perangkat, lebih baik langsung mematikan aksesnya dari sisi server.
Cara Memeriksa Header Website-mu Sekarang
Sebelum mengubah konfigurasi, cek dulu kondisi header yang sudah ada. Caranya bisa dengan curl dari terminal:
curl -I -s https://adammuiz.com/ | grep -i "strict-transport\|content-security\|x-frame\|x-content\|referrer\|permissions"
Atau gunakan layanan online seperti Security Headers oleh Scott Helme. Cukup masukkan URL, dan dalam hitungan detik kamu mendapatkan skor beserta saran perbaikan. Aku sendiri sering pakai alat ini untuk audit cepat sebelum menyebut sebuah website "aman."
Implementasi di Berbagai Server
Jika kamu pakai Nginx, semua contoh di atas bisa langsung ditempel di blok server. Untuk Apache, gunakan modul mod_headers dengan sintaks sedikit berbeda:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Untuk aplikasi PHP, kamu juga bisa mengatur header langsung dari kode:
<?php
header("Strict-Transport-Security: max-age=31536000; includeSubDomains");
header("X-Frame-Options: SAMEORIGIN");
header("X-Content-Type-Options: nosniff");
header("Referrer-Policy: strict-origin-when-cross-origin");
Tetapi sebaiknya atur di level server web. Alasannya, header yang didefinisikan di Nginx atau Apache akan berlaku untuk semua aset, termasuk file statis seperti gambar dan CSS, bukan hanya halaman PHP.
Kesalahan Umum yang Perlu Dihindari
Pertama, jangan langsung mengaktifkan CSP dengan nilai sangat ketat di website produksi. Bisa jadi beberapa fitur tiba-tiba rusak karena sumber daya pihak ketiga terblokir. Mulai dari Report-Only, periksa laporan, lalu perlahan ketatkan.
Kedua, jangan pakai 'unsafe-inline' dan 'unsafe-eval' secara membabi buta hanya karena website butuh inline script. Sebisa mungkin pindahkan script ke file eksternal. Jika terpaksa, gunakan nonce atau hash agar hanya script tertentu yang diizinkan.
Ketiga, pastikan HSTS tidak kamu aktifkan sebelum sertifikat SSL benar-benar stabil. Jika ternyata ada subdomain yang belum HTTPS, pengguna bisa kehilangan akses selama masa berlaku HSTS berjalan.
Penutup
Keamanan website tidak selalu soal membangun benteng yang rumit. Terkadang, cukup memastikan pintu tertutup rapat, jendela terkunci, dan tamu tidak diizinkan sembarangan masuk. HTTP security headers adalah langkah kecil yang sering terlupakan, tapi dampaknya besar untuk melindungi pengguna dan reputasi website-mu.
Dari HSTS yang memaksa HTTPS, CSP yang mengendalikan sumber daya, sampai Permissions-Policy yang membatasi fitur perangkat — semuanya bisa diatur dalam beberapa menit. Jika belum pernah memeriksanya, luangkan waktu sekarang juga. Siapa tahu, satu header yang kamu tambahkan hari ini justru mencegah masalah besar di masa depan.
Kalau kamu punya pengalaman menambah header keamanan atau pernah menemukan konfigurasi menarik, bagikan di kolom komentar. Aku senang belajar dari sudut pandang yang berbeda.