Keamanan Website: Praktik Terbaik Lapis demi Lapis (2026)

Advertisement
Apa Itu Praktik Terbaik Keamanan Website?
Praktik terbaik keamanan website adalah serangkaian kontrol yang menjaga website atau aplikasi web agar tidak diambil alih, di-deface, dipakai untuk menyerang pengunjungnya sendiri, atau datanya dikuras diam-diam. Praktik ini bukan satu produk atau satu pengaturan. Ini adalah tumpukan keputusan yang dimulai dari registrar domain, lalu berlanjut ke DNS, TLS, header HTTP yang dikirim server Anda, kode yang menangani login dan input, paket pihak ketiga yang menjadi fondasi aplikasi Anda, server itu sendiri, dan terakhir log yang memberi tahu Anda ketika ada yang tidak beres.
Alasan berpikir dalam lapisan sederhana saja: penyerang juga berpikir begitu. Data Breach Investigations Report 2026 dari Verizon menemukan bahwa 31% pembobolan kini berawal dari kerentanan software yang dieksploitasi, yang untuk pertama kalinya mengalahkan kredensial curian sebagai jalan masuk paling umum, dan bahwa 48% dari seluruh pembobolan melibatkan ransomware. Satu patch yang terlewat, satu API key yang bocor, atau satu halaman admin tanpa rate limiting sudah cukup. Tidak ada kontrol dalam panduan ini yang eksotis; website yang dibobol biasanya adalah website yang melewatkan hal-hal dasar di satu lapisan sambil sibuk memoles lapisan lain.
Panduan ini disusun dari luar ke dalam. Setiap praktik menjelaskan mengapa praktik itu penting, apa persisnya yang harus dikonfigurasi, dan cara memverifikasinya dengan sebuah perintah atau alat gratis, karena kegagalan paling umum yang kami lihat dalam pemeriksaan header HTTP dan pemeriksaan SSL bukanlah keputusan yang buruk, melainkan pengaturan yang diyakini sudah aktif tetapi tidak pernah dipastikan.
Tumpukan Keamanan Web: Enam Lapisan yang Harus Dilindungi
Setiap serangan terhadap website mendarat di salah satu dari enam lapisan. Tabel di bawah ini adalah peta untuk sisa panduan ini: apa yang ada di setiap lapisan, bagaimana lapisan itu biasanya diserang, dan pemeriksaan gratis mana yang memastikan pertahanan Anda benar-benar terpasang.
| Lapisan | Yang dilakukan penyerang di sini | Praktik utama | Verifikasi dengan |
|---|---|---|---|
| 1. Domain dan DNS | Membajak domain, mengubah nameserver, mengambil alih subdomain yang menggantung (dangling), mendapatkan sertifikat palsu | Registrar lock, MFA, DNSSEC, CAA, audit record usang | Pencarian WHOIS, Pencarian DNS, Pencari Subdomain |
| 2. Transport (TLS) | Menurunkan koneksi ke HTTP (downgrade), melucuti enkripsi, mengeksploitasi cipher lama, sertifikat kedaluwarsa | TLS 1.2+, HSTS dengan preload, perpanjangan otomatis | Pemeriksaan Sertifikat SSL |
| 3. Header HTTP | Menyisipkan skrip (XSS), membingkai situs untuk clickjacking, menebak (sniffing) tipe konten, membocorkan referrer | CSP, frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy | Pemeriksaan Header HTTP |
| 4. Aplikasi | Credential stuffing, injection, kontrol akses yang rusak (broken access control), CSRF, upload yang tidak aman | Argon2id + MFA + rate limit, query berparameter, otorisasi di sisi server, cookie SameSite | Code review, OWASP ZAP, Penguji Kekuatan Kata Sandi |
| 5. Dependensi | Paket yang diracuni, CVE yang sudah diketahui di library, pipeline CI yang disusupi | Lockfile, audit, versi yang di-pin, SBOM, token dengan hak akses minimum | npm audit, Dependabot, Trivy |
| 6. Server dan operasional | Port terbuka, kredensial default, patch yang terlewat, tanpa backup, tanpa log | Firewall, SSH hanya dengan kunci, patching, backup 3-2-1, logging terpusat | Pemeriksa Port, Pemeriksaan Daftar Hitam IP, Pemeriksa Kesehatan Domain |
Advertisement
Lapisan 1: Kunci Domain dan DNS
Semua hal lain dalam panduan ini berasumsi Anda masih menguasai domain Anda. Jika penyerang bisa login ke registrar Anda atau mengubah nameserver, mereka bisa mengarahkan trafik Anda ke mana saja, mendapatkan sertifikat yang valid atas nama domain Anda, dan membaca setiap email yang dikirim kepada Anda, tanpa satu baris pun kode aplikasi Anda sempat berjalan. Karena itu, keamanan domain dan DNS adalah praktik terbaik keamanan website yang pertama, dan hampir seluruhnya berupa konfigurasi.
Mulailah dengan pencarian WHOIS pada domain Anda sendiri dan pastikan tiga hal: kode statusnya mencakup clientTransferProhibited, tanggal kedaluwarsanya masih lebih dari setahun lagi, dan registrarnya memang registrar tempat Anda punya akun. Cukup sering domain bisnis ternyata masih berada di akun registrar milik mantan kontraktor. Panduan pencarian WHOIS kami menjelaskan setiap kode status yang akan Anda temui.
Registrar Lock, MFA, dan Pengingat Masa Berlaku
Aktifkan registrar lock (disebut juga transfer lock) agar domain tidak bisa dipindahkan ke registrar lain tanpa Anda membukanya secara eksplisit, lalu aktifkan autentikasi multi-faktor (MFA) pada akun registrar itu sendiri. Akun registrar adalah sasaran phishing favorit justru karena satu login mengendalikan semua yang ada di bawahnya. Gunakan kunci keamanan fisik (hardware key) atau aplikasi autentikator, bukan SMS, di mana pun registrar mengizinkannya.
Atur domain agar diperpanjang otomatis dengan metode pembayaran yang tidak akan kedaluwarsa, dan tetap pasang pengingat kalender 60 hari sebelum tanggal kedaluwarsa. Domain yang kedaluwarsa disambar drop-catcher dalam hitungan jam, dan pembelinya mewarisi email Anda, trafik Anda, serta login OAuth apa pun yang memercayai domain Anda.
Registry lock (penguncian manual di tingkat registry yang dilakukan lewat jalur terpisah/out-of-band) layak dibayar lebih untuk domain yang menjadi tumpuan bisnis; penguncian ini mencegah perubahan nameserver bahkan jika akun registrar berhasil dibobol.
Pisahkan perannya. Orang yang membayar domain, akun yang memilikinya, dan penyedia DNS masing-masing harus terdokumentasi dan tidak terikat pada kotak surat satu karyawan.
Aktifkan privasi WHOIS agar detail kontak Anda tidak menjadi peta bagi pelaku phishing, dan gunakan alamat peran yang dipantau, seperti
domains@, pada akun tersebut.
Tandatangani Zona dengan DNSSEC
DNSSEC menandatangani zona DNS Anda sehingga resolver bisa mendeteksi jawaban palsu. Tanpanya, penyerang yang mampu meracuni cache resolver bisa mengirim pengunjung Anda ke server palsu, sementara browser mereka tetap menampilkan nama domain Anda. Sebagian besar penyedia DNS terkelola (Cloudflare, Route 53, Google Cloud DNS, dan banyak registrar) mengaktifkannya cukup dengan satu tombol; satu-satunya langkah manual adalah memublikasikan record DS di registrar Anda. Verifikasi dengan dig, atau dengan pemeriksaan DNSSEC di dalam Pemeriksa Kesehatan Domain:
dig +dnssec +short yourdomain.com A
# A signed zone returns the record AND an RRSIG line:
# 203.0.113.10
# A 13 2 3600 20261015000000 20260924000000 34505 yourdomain.com. Kx3f...==
dig +short yourdomain.com DS
# A DS record at the parent zone proves the chain of trust is complete
# 34505 13 2 6A1B...C9Batasi Penerbitan Sertifikat dengan CAA
Record CAA (RFC 8659) memberi tahu otoritas sertifikat (CA) mana saja yang boleh menerbitkan sertifikat untuk domain Anda. Setiap CA publik wajib memeriksanya sebelum menerbitkan sertifikat, sehingga record CAA menutup pintu bagi penyerang yang berhasil mengelabui validasi domain di CA lain. Tiga record sudah mencakup kasus umum: siapa yang boleh menerbitkan, siapa yang boleh menerbitkan sertifikat wildcard, dan ke mana permintaan yang ditolak harus dilaporkan:
yourdomain.com. CAA 0 issue "letsencrypt.org"
yourdomain.com. CAA 0 issuewild ";"
yourdomain.com. CAA 0 iodef "mailto:security@yourdomain.com"Audit Record Usang: Subdomain Takeover
Subdomain takeover terjadi ketika sebuah record DNS masih mengarah ke layanan yang sudah tidak Anda gunakan: CNAME ke situs GitHub Pages yang sudah dihapus, aplikasi Azure, bucket S3, atau hostname milik vendor SaaS. Siapa pun bisa mendaftarkan target yang ditinggalkan itu lalu menyajikan konten di old-app.yourdomain.com atas nama Anda, lengkap dengan sertifikat yang valid. Ini salah satu temuan paling umum di program bug bounty karena tidak ada yang ingat record itu masih ada.
Jalankan domain Anda melalui Pencari Subdomain, yang membaca log certificate transparency, sehingga Anda melihat setiap hostname yang pernah diterbitkan sertifikatnya. Lalu resolve masing-masing dengan pencarian DNS dan hapus setiap record yang targetnya mengembalikan NXDOMAIN atau halaman "no such app" dari penyedia layanan. Ulangi setiap kuartal, dan jadikan penghapusan record DNS bagian dari proses penonaktifan layanan apa pun.
Lapisan 2: HTTPS dan TLS yang Dikonfigurasi dengan Benar
HTTPS bukan lagi sekadar praktik terbaik; HTTPS adalah standar minimum, dan browser menandai halaman HTTP biasa sebagai "Tidak aman". Yang masih membedakan situs yang aman dari situs yang sekadar terenkripsi adalah versi TLS yang Anda terima, apakah HTTP masih bisa dipakai untuk menjangkau Anda sama sekali, dan apakah perpanjangan sertifikat sudah cukup otomatis untuk bertahan menghadapi pemangkasan masa berlaku sertifikat yang dimulai pada Maret 2026.
Advertisement
Minimal TLS 1.2, Utamakan TLS 1.3
TLS 1.0 dan 1.1 secara resmi dinyatakan usang (deprecated) oleh RFC 8996 pada 2021, dan tidak ada browser saat ini yang masih menegosiasikannya. Nonaktifkan keduanya di server, utamakan TLS 1.3 (yang membuang semua cipher yang diketahui lemah dan menyelesaikan handshake dalam satu kali round trip), dan pertahankan TLS 1.2 hanya dengan cipher suite AEAD seperti ECDHE-ECDSA-AES128-GCM-SHA256 atau ECDHE-RSA-CHACHA20-POLY1305.
Ada dua baris yang penting saat Anda menguji dari luar: protokol yang dinegosiasikan, dan Verify return code: 0, yang berarti seluruh rantai sertifikat berhasil divalidasi. Sertifikat intermediate yang hilang adalah penyebab paling umum laporan "jalan di Chrome, gagal di curl dan Android"; panduan kami tentang rantai sertifikat SSL menunjukkan cara memperbaikinya, dan Pemeriksaan Sertifikat SSL langsung menandai rantai yang tidak lengkap. Berikut pemeriksaan yang dijalankan terhadap dnsrobot.net:
echo | openssl s_client -connect dnsrobot.net:443 -servername dnsrobot.net 2>/dev/null \
| grep -E 'Protocol|Cipher|Verify return'
# Protocol : TLSv1.3
# Cipher : TLS_AES_256_GCM_SHA384
# Verify return code: 0 (ok)
# Confirm the old versions are refused:
openssl s_client -connect dnsrobot.net:443 -tls1_1 2>&1 | grep -iE 'alert|no protocols'HSTS: Jangan Biarkan Browser Memakai HTTP Lagi
Mengalihkan HTTP ke HTTPS saja tidak cukup. Permintaan pertama yang dibuat pengunjung ke http://yourdomain.com tetap dikirim dalam teks biasa, dan penyerang di jaringan yang sama bisa menjawabnya lebih dulu sebelum redirect Anda. HTTP Strict Transport Security (RFC 6797) mengatasi masalah ini: begitu browser pernah melihat header tersebut, browser akan menulis ulang setiap URL http:// untuk domain Anda menjadi https:// sebelum mengirim apa pun.
Gunakan max-age minimal satu tahun (31536000 detik), tambahkan includeSubDomains setelah semua subdomain melayani HTTPS, lalu daftarkan domain di hstspreload.org agar domain Anda tertanam langsung (hard-coded) di Chrome, Firefox, Safari, dan Edge. Preload menutup celah kunjungan pertama sepenuhnya. Verifikasi header ini dengan Pemeriksaan Header HTTP, yang menilai HSTS sebagai bagian dari skor keamanan A sampai F.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadSertifikat 47 Hari: Otomatiskan Perpanjangan Sekarang
Ballot SC-081 dari CA/Browser Forum memangkas masa berlaku maksimum setiap sertifikat TLS publik secara bertahap. Pemangkasan pertama berlaku sejak 15 Maret 2026, sehingga sertifikat apa pun yang Anda beli atau perpanjang hari ini sudah dibatasi 200 hari, dan pada 2029 sertifikat perlu diganti kira-kira setiap enam minggu:
| Tanggal berlaku | Masa berlaku maksimum sertifikat | Penggunaan ulang validasi domain |
|---|---|---|
| Sebelum 15 Maret 2026 | 398 hari | 398 hari |
| 15 Maret 2026 | 200 hari | 200 hari |
| 15 Maret 2027 | 100 hari | 100 hari |
| 15 Maret 2029 | 47 hari | 10 hari |
Perpanjangan manual tidak akan sanggup mengikuti jadwal ini. Praktik terbaiknya adalah penerbitan yang sepenuhnya otomatis melalui ACME: Let's Encrypt atau Google Trust Services lewat certbot, acme.sh, Caddy, atau sertifikat otomatis bawaan Cloudflare, Vercel, Netlify, dan sebagian besar panel hosting. Uji jalur perpanjangan sebelum Anda membutuhkannya (certbot renew --dry-run untuk certbot); kegagalan yang perlu diwaspadai adalah record CAA atau aturan firewall yang ditambahkan sejak perpanjangan terakhir dan kini memblokir validasi. Apa pun yang Anda gunakan, pantau juga tanggal kedaluwarsa dari luar: Pemeriksaan Sertifikat SSL menampilkan sisa hari, dan sertifikat yang kedaluwarsa mengubah setiap kunjungan menjadi peringatan browser satu halaman penuh.
Lapisan 3: Header Keamanan HTTP (Security Headers)
Security header adalah instruksi yang diberikan server kepada browser tentang apa yang boleh dan tidak boleh dilakukan terhadap halaman Anda: skrip mana yang boleh berjalan, apakah halaman boleh dibingkai (frame), apakah browser boleh menebak tipe konten, dan apa yang perlu diberitahukan ke situs lain tentang asal pengunjung. Header ini gratis, berlaku untuk semua halaman sekaligus, dan memblokir seluruh kelas serangan. Header juga merupakan lapisan yang paling sering dikonfigurasi setengah benar oleh kebanyakan situs, itulah sebabnya Pemeriksaan Header HTTP memberi nilai untuknya. Berikut header yang dikirim dnsrobot.net, dipangkas hanya pada security header:
curl -sI https://dnsrobot.net/ | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy'
strict-transport-security: max-age=31536000; includeSubDomains; preload
content-security-policy: default-src 'self'; script-src 'self' ... https://*.googletagmanager.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
x-frame-options: DENY
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
permissions-policy: camera=(self), microphone=(), geolocation=(), payment=(), usb=()Tujuh Header yang Wajib Dikirim Setiap Situs
Inilah nilai yang perlu Anda tuju untuk situs pada umumnya. Lima yang pertama adalah yang memengaruhi nilai Anda; dua yang terakhir adalah tambahan murah setelah yang lain terpasang.
| Header | Nilai yang direkomendasikan | Yang dicegah |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | Downgrade protokol, pencurian cookie melalui HTTP |
Content-Security-Policy | script-src berbasis nonce dengan 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none' | Cross-site scripting (XSS), injeksi data, clickjacking |
X-Content-Type-Options | nosniff | MIME sniffing yang mengubah file upload menjadi skrip yang bisa dieksekusi |
Referrer-Policy | strict-origin-when-cross-origin | Bocornya URL lengkap (token, kata kunci pencarian) ke pihak ketiga |
Permissions-Policy | camera=(), microphone=(), geolocation=(), payment=() | Skrip pihak ketiga yang diam-diam memakai API browser yang sensitif |
X-Frame-Options | DENY (fallback lama untuk frame-ancestors) | Clickjacking di browser tanpa CSP Level 2 |
Cross-Origin-Opener-Policy | same-origin | Serangan lintas jendela melalui window.opener |
Content Security Policy Tanpa Merusak Situs
Content Security Policy adalah pertahanan paling efektif terhadap XSS karena mencegah skrip sisipan berjalan bahkan ketika ada bug injeksi. Masalahnya, kebijakan yang ketat akan merusak skrip inline atau tag pihak ketiga yang terlupakan. Pendekatan modern, yang direkomendasikan Google dan didokumentasikan di MDN, adalah kebijakan berbasis nonce: server membuat nonce acak untuk setiap respons, memasangnya pada setiap tag script yang memang sengaja dirender, dan browser menolak semua yang lain.
'strict-dynamic' adalah yang membuat kebijakan ini praktis: skrip yang memiliki nonce boleh memuat skrip lain (analitik, tag manager, widget) tanpa harus memasukkan masing-masing ke allowlist, sementara token https: dan 'unsafe-inline' diabaikan oleh browser modern dan hanya berfungsi sebagai fallback untuk browser lama. Terapkan dulu dengan Content-Security-Policy-Report-Only, pantau laporan pelanggaran selama seminggu, lalu beralih ke mode enforce. Framework seperti Next.js, Rails, dan Django punya dukungan nonce bawaan; situs statis bisa memakai script-src berbasis hash sebagai gantinya.
Content-Security-Policy:
script-src 'nonce-r4nd0m1z3dV4lu3' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
form-action 'self';
report-to csp-endpoint
<!-- Only scripts carrying the nonce run; strict-dynamic lets them load their own dependencies -->
<script nonce="r4nd0m1z3dV4lu3" src="/app.js"></script>Clickjacking: frame-ancestors dan X-Frame-Options
Clickjacking memuat situs Anda secara tak terlihat di dalam halaman penyerang dan mengelabui pengunjung agar mengklik tombol yang tidak bisa mereka lihat. frame-ancestors 'none' di CSP (atau 'self' jika Anda menyematkan halaman Anda sendiri) mencegahnya di semua browser saat ini, dan X-Frame-Options: DENY menangani browser yang lebih lama. Jika Anda sengaja menyediakan widget yang bisa disematkan, kecualikan hanya path tersebut dan hanya untuk origin yang membutuhkannya; panduan X-Frame-Options kami menjelaskan aturan server yang tepat dan error "refused to connect" yang akan Anda temui saat pengujian.
nosniff, Referrer-Policy, Permissions-Policy, dan COOP
X-Content-Type-Options: nosniff menghentikan browser dari menebak-nebak Content-Type, yang menjadi penyebab "gambar" unggahan pengguna yang berisi HTML berubah menjadi halaman yang bisa dieksekusi. Referrer-Policy: strict-origin-when-cross-origin (default di browser saat ini, tetapi tetap atur secara eksplisit) hanya mengirim origin Anda ke situs lain, sehingga token reset kata sandi dan kueri pencarian di URL tetap privat. Permissions-Policy menonaktifkan fitur browser yang tidak Anda pakai, sehingga skrip pihak ketiga yang disusupi tidak bisa membuka kamera atau membaca lokasi. Cross-Origin-Opener-Policy: same-origin memutus tautan window.opener ke halaman yang Anda buka, yang memblokir satu kelas serangan lintas jendela.
Header yang perlu dihapus juga penting: Server dan X-Powered-By mengiklankan versi software yang persis kepada scanner kerentanan, sedangkan X-XSS-Protection sudah usang dan bisa menimbulkan bug di browser lama, jadi atur ke 0 atau hapus saja. Pendeteksi CMS menunjukkan apa yang bisa dipelajari scanner tentang stack Anda hanya dari header.
Lapisan 4: Autentikasi yang Tahan Credential Stuffing
Penyerang jarang menebak kata sandi satu per satu. Mereka memutar ulang miliaran pasangan email dan kata sandi yang bocor dari situs lain (credential stuffing) dan mem-phishing sisanya. Karena itu, praktik terbaik autentikasi terdiri dari tiga bagian: simpan kata sandi sedemikian rupa sehingga kebocoran database tidak berarti kebocoran kata sandi, buat kata sandi curian tidak berguna jika berdiri sendiri, dan buat brute force terlalu lambat untuk berarti. OWASP menempatkan Authentication Failures (kegagalan autentikasi) di posisi A07 dalam OWASP Top 10:2025.
Advertisement
Hash Kata Sandi dengan Argon2id atau bcrypt
Jangan pernah menyimpan kata sandi, dan jangan pernah menyimpan hash cepat dari kata sandi. MD5, SHA-1, bahkan SHA-256 dirancang untuk cepat, sehingga tabel hash semacam itu yang bocor bisa diuji dengan miliaran tebakan per detik hanya dengan satu GPU. Gunakan fungsi hashing kata sandi yang lambat dan memory-hard dengan salt unik untuk setiap kata sandi. OWASP Password Storage Cheat Sheet merekomendasikan, secara berurutan:
Argon2id dengan memori minimal 19 MiB, 2 iterasi, dan tingkat paralelisme 1 (atau 46 MiB dengan 1 iterasi).
scrypt dengan N = 2^17, r = 8, p = 1 jika Argon2 tidak tersedia.
bcrypt dengan work factor 10 atau lebih (perhatikan batas input 72 byte; melakukan pre-hash pada kata sandi yang lebih panjang perlu kehati-hatian).
PBKDF2-HMAC-SHA256 dengan 600.000 iterasi, hanya jika kepatuhan FIPS mengharuskannya.
// Node.js with the argon2 package
import argon2 from "argon2";
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // KiB = 19 MiB
timeCost: 2,
parallelism: 1,
});
// Later, on login:
const ok = await argon2.verify(hash, submittedPassword);Aturan Kata Sandi yang Benar-Benar Membantu (NIST SP 800-63B)
Aturan komposisi yang masih diterapkan kebanyakan situs (satu huruf besar, satu simbol, ganti setiap 90 hari) menghasilkan kata sandi yang mudah ditebak seperti Summer2026! dan mendorong orang untuk memakainya berulang kali. Panduan NIST SP 800-63B terbaru menggantinya dengan aturan yang mengukur hal yang benar-benar penting:
Minimal 8 karakter jika MFA juga diwajibkan, dan minimal 15 karakter untuk kata sandi yang dipakai tanpa faktor lain; izinkan panjang hingga setidaknya 64 karakter.
Tanpa aturan komposisi dan tanpa kewajiban rotasi berkala; wajibkan penggantian hanya jika ada bukti kata sandi telah disusupi.
Periksa setiap kata sandi baru terhadap daftar kebocoran (range API dari Have I Been Pwned memungkinkan hal ini tanpa mengirim kata sandinya) dan tolak kata sandi yang diketahui sudah bocor.
Izinkan tempel (paste) dan pengelola kata sandi, terima spasi dan Unicode, serta tampilkan pengukur kekuatan berdasarkan entropi, bukan aturan.
Penguji Kekuatan Kata Sandi kami menunjukkan perbedaan ukuran-ukuran ini dengan aturan lama: alat ini memperkirakan waktu pembobolan dari entropi dan deteksi pola, serta memeriksa kata sandi terhadap data kebocoran, yang jauh lebih berguna daripada pesan merah "harus ada simbol".
MFA dan Passkey
Autentikasi multi-faktor mengubah kata sandi curian menjadi jalan buntu. Tawarkan kepada semua pengguna dan wajibkan untuk peran admin, keuangan, dan dukungan pelanggan. Urutkan pilihannya berdasarkan ketahanan terhadap phishing: passkey dan kunci keamanan FIDO2 tidak bisa di-phishing karena kredensialnya terikat pada origin Anda yang asli; aplikasi autentikator (TOTP) sudah bagus; kode SMS lebih baik daripada tidak ada, tetapi bisa disadap melalui SIM swapping. Passkey didukung di semua browser dan sistem operasi saat ini dan menghilangkan kata sandi sepenuhnya, yang sekaligus menghapus credential stuffing sebagai sebuah kategori serangan.
Lindungi jalur pemulihan akun secermat login: kode pemulihan disimpan dalam bentuk hash, reset lewat email dengan token sekali pakai yang kedaluwarsa dalam 15 menit, dan tanpa pertanyaan keamanan.
Rate Limiting, Penguncian Akun, dan Pertahanan terhadap Bot
Terapkan rate limit pada endpoint login, registrasi, reset kata sandi, dan MFA per IP dan per akun, lalu kembalikan 429 Too Many Requests dengan header Retry-After begitu batasnya tercapai (panduan kami tentang HTTP error 429 membahas bagaimana klien seharusnya merespons). Kombinasikan dengan jeda yang makin panjang atau penguncian sementara setelah kegagalan berulang pada satu akun, serta CAPTCHA atau tantangan proof-of-work untuk endpoint yang menjadi sasaran serangan terdistribusi. Catat setiap login yang gagal beserta IP sumbernya agar pola serangan credential stuffing terlihat dalam hitungan menit, bukan bulan.
# nginx: 5 login attempts per minute per client IP
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location = /api/login {
limit_req zone=login burst=4 nodelay;
limit_req_status 429;
proxy_pass http://app;
}Sesi, Cookie, dan CSRF
Setelah login, cookie sesi adalah pengguna itu sendiri, jadi cookie ini layak mendapat perlindungan yang sama dengan kata sandi. Tiga atribut cookie dan satu prefiks nama melakukan sebagian besar pekerjaannya:
Secureberarti cookie tidak pernah dikirim melalui HTTP biasa, sehingga tidak bisa disadap di Wi-Fi publik.HttpOnlymembuat cookie tidak terlihat oleh JavaScript, sehingga bug XSS tidak bisa membacanya.SameSite=Lax(atauStrictuntuk panel admin) menjauhkan cookie dari permintaan POST lintas situs, yang menetralkan sebagian besar serangan CSRF.Prefiks
__Host-membuat browser menolak cookie kecuali cookie tersebutSecure, memilikiPath=/, dan tanpa atributDomain, sehingga subdomain tidak bisa menimpanya.
Set-Cookie: __Host-session=9f1c7e2a...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=28800CSRF: Lapisan Kedua di Belakang SameSite
Cross-site request forgery (CSRF) mengelabui browser yang sedang login agar mengirim permintaan yang mengubah state ke situs Anda dari halaman lain. Cookie SameSite menghentikan kasus yang umum, tetapi tetap pasang pertahanan kedua pada setiap permintaan non-GET: token anti-CSRF per sesi di field tersembunyi atau header kustom, atau pemeriksaan bahwa header Origin (atau Sec-Fetch-Site) cocok dengan origin Anda sendiri. Sebagian besar framework (Django, Rails, Laravel, server action Next.js) melakukannya secara default; kesalahannya adalah menonaktifkan perlindungan ini untuk endpoint API lalu memanggil endpoint itu dari browser.
ID Sesi, Rotasi, dan JWT
Buat ID sesi dengan keacakan minimal 128 bit, rotasi ID saat login dan setiap kali hak akses berubah untuk menggagalkan session fixation, akhiri sesi setelah tidak ada aktivitas, dan beri pengguna tombol "keluar dari semua perangkat" yang membatalkan sesi di sisi server. Untuk JWT, buat masa berlakunya singkat (hitungan menit, dengan refresh token yang bisa dicabut), jangan pernah menyimpannya di localStorage tempat skrip apa pun bisa membacanya, dan perlakukan signing key yang bocor sebagai pembobolan penuh, karena setiap token yang pernah ditandatanganinya kini bisa dipalsukan.
Injection dan XSS: Validasi Input, Encode Output
Injection (A05:2025) dan cross-site scripting adalah kesalahan yang sama di tempat berbeda: data dari pengguna diserahkan ke interpreter (SQL, shell, kueri LDAP, halaman HTML) seolah-olah data itu kode. Solusinya pun sama di mana pun: pisahkan data dari kode, dan jangan pernah menyusun perintah dengan penggabungan string.
Advertisement
Query Berparameter, Bukan Menyusun String
Untuk SQL, gunakan prepared statement atau ORM yang membuatnya; database kemudian memperlakukan input sebagai nilai yang tidak akan pernah bisa mengubah struktur query. Aturan yang sama berlaku untuk perintah shell (kirim array argumen, jangan pernah string), filter NoSQL (tolak objek operator seperti {"$gt": ""} pada input pengguna), dan path file (resolve path-nya lalu pastikan tetap berada di bawah direktori yang dimaksud).
// Vulnerable: the input becomes part of the query text
const rows = await db.query(`SELECT * FROM users WHERE email = '${email}'`);
// Safe: the driver sends the value separately from the query
const rows = await db.query("SELECT * FROM users WHERE email = $1", [email]);
// Python / psycopg: same idea
cur.execute("SELECT * FROM users WHERE email = %s", (email,))Encoding Output Menghentikan XSS
Cross-site scripting terjadi saat teks yang dikendalikan pengguna ditulis ke halaman tanpa di-encode sesuai konteks tempatnya berada. Mesin templating modern (React dan JSX, Vue, Jinja2, Blade, ERB) melakukan encoding secara default; XSS saat ini biasanya berasal dari celah pengecualiannya (escape hatch): dangerouslySetInnerHTML, v-html, |safe, innerHTML, serta penyusunan URL atau event handler inline dari data pengguna. Lakukan encoding sesuai konteks yang tepat, dan sanitasi HTML kaya (rich HTML) dengan library khusus seperti DOMPurify, bukan dengan regex.
| Tempat data berada | Encode sebagai | Contoh |
|---|---|---|
| Body HTML | Entitas HTML | < menjadi <, " menjadi " |
| Atribut HTML | Entitas di dalam atribut berkutip | Selalu beri tanda kutip pada atribut; encode " dan ' |
| JavaScript | Jangan menyisipkan ke dalam teks skrip; kirim data melalui atribut data- atau blok JSON <script type="application/json"> | </script> di dalam string menjadi \u003c/script\u003e |
| Parameter URL | Percent-encoding | encodeURIComponent(value) |
| Nilai CSS | Hindari sepenuhnya; pilih nama class dari allowlist | Jangan pernah menyisipkan input pengguna ke dalam style |
SSRF, Upload File, dan Deserialisasi
Server-side request forgery (SSRF): jika server Anda mengambil URL yang diberikan pengguna (webhook, proxy gambar, pratinjau tautan), penyerang bisa mengarahkannya ke layanan internal atau ke endpoint metadata cloud 169.254.169.254 dan membaca kredensial. Resolve hostname terlebih dahulu, tolak rentang IP privat dan link-local, nonaktifkan redirect, dan tempatkan fetcher di segmen jaringan yang tidak bisa menjangkau apa pun di jaringan internal.
Upload file: validasi tipe file dengan memeriksa isinya, bukan ekstensinya atau Content-Type dari klien; terapkan batas ukuran; simpan file di luar web root atau di object storage dengan nama acak yang Anda buat sendiri; dan sajikan file dari origin terpisah dengan nosniff dan Content-Disposition: attachment jika memungkinkan. Jangan pernah membiarkan file upload berada di lokasi yang akan dieksekusi oleh web server.
Deserialisasi dan mass assignment: jangan pernah melakukan deserialisasi data yang tidak tepercaya dengan format yang bisa membuat instance class sembarang (serialisasi native Java, pickle di Python, unserialize di PHP, YAML dengan tag kustom); gunakan JSON dengan skema. Ikat body request ke allowlist field yang eksplisit agar pengguna tidak bisa mengirim POST "role": "admin" ke model yang kebetulan memiliki kolom tersebut.
Broken Access Control: Risiko Nomor Satu
Broken Access Control (kontrol akses yang rusak) menduduki posisi teratas OWASP Top 10 sejak 2021 dan tetap bertahan sebagai A01:2025. Ini bukan satu bug, melainkan kebiasaan: memeriksa siapa seseorang (autentikasi) tetapi lupa memeriksa apa yang boleh ia akses (otorisasi) di setiap permintaan. Bentuk klasiknya adalah insecure direct object reference (IDOR): GET /api/invoices/1042 berfungsi untuk pemilik invoice tersebut, dan juga untuk siapa pun yang mengganti angkanya.
Tolak secara default. Setiap route memerlukan aturan eksplisit yang memberikan akses; aturan yang tidak ada berarti 403, bukan 200.
Terapkan di server, per objek. Menyembunyikan tombol di UI bukanlah kontrol akses. Setiap operasi baca dan tulis harus memastikan pengguna saat ini memiliki atau diizinkan mengakses record spesifik tersebut, termasuk di endpoint massal, fitur ekspor, dan background job.
Gunakan ID yang tidak bisa ditebak jika membantu (UUID), tetapi jangan pernah mengandalkannya: menyamarkan bukanlah otorisasi.
Perketat CORS.
Access-Control-Allow-Origin: *dengan kredensial, atau memantulkanOriginapa pun yang dikirim request, sama saja dengan menyerahkan API Anda ke website mana pun yang dikunjungi pengguna.Nonaktifkan directory listing, blokir
.git,.env, file backup, dan file konfigurasi di tingkat web server, serta jauhkan panel admin dari internet publik atau lindungi dengan MFA dan allowlist IP.Terapkan rate limit dan catat kegagalan otorisasi. Lonjakan 403 dari satu sesi adalah tanda serangan enumerasi yang sedang berlangsung.
// Express: ownership check on every object access
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
const invoice = await Invoice.findById(req.params.id);
if (!invoice || invoice.ownerId !== req.user.id) {
return res.status(404).end(); // 404, not 403: don't confirm the record exists
}
res.json(invoice);
});Lapisan 5: Dependensi dan Software Supply Chain
Aplikasi web pada umumnya berisi mungkin hanya 5% kode yang Anda tulis dan 95% kode yang Anda unduh. Itulah sebabnya Software Supply Chain Failures (kegagalan rantai pasok software) langsung masuk di posisi A03 dalam OWASP Top 10 2025, dan mengapa eksploitasi kerentanan menyalip kredensial curian dalam DBIR 2026. Pada September 2025, satu maintainer yang terkena phishing menyisipkan malware pencuri kripto ke chalk, debug, dan 16 paket npm lain yang secara total diunduh lebih dari dua miliar kali per minggu; setiap proyek yang menginstal versi yang tidak di-pin selama rentang waktu itu otomatis ikut menariknya.
Commit lockfile (
package-lock.json,yarn.lock,pnpm-lock.yaml,poetry.lock,go.sum) dan instal dengannpm cidi CI agar build bisa direproduksi dan rilis upstream baru tidak bisa menyelinap masuk tanpa ditinjau.Scan terus-menerus:
npm audit,pip-audit,bundler-audit, GitHub Dependabot atau Renovate untuk pembaruan, serta scanner container seperti Trivy atau Grype untuk lapisan OS.Tunda upgrade non-keamanan beberapa hari (
minimumReleaseAgedi Renovate) agar rilis yang diracuni biasanya sudah ditarik sebelum Anda mengadopsinya, tetapi terapkan patch keamanan segera.Pin action dan skrip pihak ketiga ke SHA commit di CI, dan gunakan Subresource Integrity (
integrity="sha384-...") pada skrip apa pun yang Anda muat dari CDN publik.Beri CI hak akses seminimal mungkin: token read-only jika memungkinkan, kredensial OIDC berumur pendek alih-alih secret berumur panjang, dan hak publikasi yang dibatasi hanya untuk job rilis.
Buat SBOM (CycloneDX atau SPDX) saat build agar Anda bisa menjawab "apakah kita terdampak?" dalam hitungan menit saat CVE sekelas Log4Shell berikutnya muncul.
# Reproducible install + audit in CI
npm ci --ignore-scripts
npm audit --audit-level=high
# Pin a GitHub Action to a commit, not a floating tag
# uses: actions/checkout@v4 <- can change underneath you
# uses: actions/checkout@<full-commit-sha> # v4.2.2
# Subresource Integrity for a CDN script (hash from: openssl dgst -sha384 -binary lib.min.js | openssl base64 -A)
<script src="https://cdn.example.com/lib.min.js"
integrity="sha384-<base64-hash>"
crossorigin="anonymous"></script>Jika Anda menjalankan WordPress atau CMS lain, aturan yang sama berlaku untuk plugin dan tema, yang menjadi titik awal sebagian besar kasus pembobolan CMS. Selalu perbarui core dan setiap plugin, hapus yang tidak Anda pakai, dan periksa apa yang bisa diketahui scanner tentang versi Anda dengan Pendeteksi CMS.
Lapisan 6: Hardening Server (Port, Patch, Secret, Backup)
Lapisan aplikasi tidak ada artinya jika server di bawahnya menerima login SSH dengan kata sandi, menjalankan database di port publik, atau belum pernah di-patch sejak pertama kali dibangun. Praktik terbaik server memang membosankan, dan justru di situlah ransomware masuk.
Tutup Setiap Port yang Tidak Anda Layani
Web server publik membutuhkan port 80 dan 443 terbuka, serta SSH dari rentang IP Anda sendiri. Database (3306, 5432, 27017), Redis (6379), Elasticsearch (9200), panel admin, dan endpoint metrik sebaiknya hanya bind ke localhost atau jaringan privat. Periksa dari luar dengan Pemeriksa Port setelah setiap perubahan, karena itulah sudut pandang yang didapat penyerang, dan security group di cloud mudah salah dibaca.
# Ubuntu: default-deny firewall, allow only web + SSH from your office range
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
sudo ufw enable
# SSH: keys only, no root password login
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sudo systemctl reload sshPatch Secara Terjadwal, Jauhkan Secret dari Kode
Aktifkan pembaruan keamanan otomatis (unattended) untuk sistem operasi, berlangganan milis keamanan untuk runtime dan framework Anda, dan perlakukan CVE kritis pada apa pun yang terhubung ke internet sebagai pekerjaan yang harus selesai hari itu juga. Jalankan layanan sebagai pengguna tanpa hak istimewa, di dalam container atau dengan sandboxing systemd, sehingga proses yang disusupi tidak bisa membaca seluruh mesin.
Secret (kata sandi database, API key, signing key) tidak boleh berada di repository, di layer image Docker, atau di JavaScript sisi klien. Muat secret dari environment variable yang disuntikkan saat deploy atau dari secrets manager, rotasi saat seseorang yang memiliki akses keluar, dan pindai riwayat repository dengan tool seperti gitleaks, karena kunci yang pernah di-commit sekali akan tetap dianggap bocor selamanya, bahkan setelah commit-nya dihapus.
Backup yang Tahan Ransomware, dan CDN di Depan Server
Ikuti aturan 3-2-1: tiga salinan, di dua media berbeda, satu di luar lokasi (off-site), dan jadikan setidaknya satu salinan immutable atau offline agar ransomware yang mencapai server tidak bisa ikut mengenkripsi backup. Enkripsi backup, sertakan database dan direktori upload, dan yang terpenting, uji proses restore secara terjadwal. Backup yang belum pernah dipulihkan hanyalah harapan, bukan rencana. Waktu pemulihan adalah faktor yang menentukan apakah sebuah insiden hanya menjadi gangguan layanan atau peristiwa yang mengakhiri perusahaan.
Tempatkan CDN atau WAF (Cloudflare, Fastly, AWS CloudFront dengan WAF, atau layanan setara dari host Anda) di depan origin. CDN atau WAF menyerap DDoS volumetrik, menerapkan aturan terkelola untuk payload injection yang umum dan bot jahat, menyembunyikan IP origin Anda, dan memberi Anda tempat untuk menerapkan rate limit dan aturan geografis tanpa menyentuh aplikasi. Lalu batasi firewall origin agar hanya rentang IP milik CDN yang bisa mengakses port 443 secara langsung; jika tidak, penyerang cukup memutarinya. Cek Hosting Website menunjukkan apakah origin asli sebuah situs terekspos di balik CDN-nya.
Autentikasi Email: SPF, DKIM, dan DMARC
Keamanan web juga mencakup email yang membawa reset kata sandi, invoice, dan balasan dukungan pelanggan Anda. Tanpa SPF, DKIM, dan DMARC, siapa pun bisa mengirim email sebagai billing@yourdomain.com, dan sejak Februari 2024 Google dan Yahoo mewajibkan ketiganya bagi pengirim massal. Set lengkapnya terdiri dari tiga record TXT DNS:
yourdomain.com. TXT "v=spf1 include:_spf.google.com -all"
google._domainkey.yourdomain.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
_dmarc.yourdomain.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s"Mulai DMARC di p=none untuk mengumpulkan laporan, lalu naik ke p=quarantine dan kemudian p=reject setelah setiap pengirim yang sah (platform marketing, helpdesk, CRM) lolos alignment. Tambahkan record MTA-STS dan TLS-RPT untuk memaksa pengiriman terenkripsi ke server email Anda, dan publikasikan null MX (MX 0 .) pada domain yang tidak pernah mengirim email agar domain itu sama sekali tidak bisa dipalsukan. Verifikasi setiap record dengan Pemeriksa Rekaman SPF, Pemeriksa DKIM, dan Pemeriksa DMARC, serta periksa IP pengirim Anda terhadap daftar blokir dengan Pemeriksaan Daftar Hitam IP jika tingkat keterkiriman (deliverability) menurun.
Log, Pantau, dan Bersiap Menghadapi Pembobolan
Dua dari sepuluh kategori OWASP 2025 membahas apa yang terjadi setelah sebuah kesalahan: Security Logging and Alerting Failures (A09) dan kategori baru Mishandling of Exceptional Conditions (A10). Pembobolan pada umumnya masih tidak terdeteksi selama berbulan-bulan karena buktinya tidak pernah dicatat, atau sudah dicatat tetapi tidak ada yang melihatnya.
Catat event keamanan beserta konteksnya: setiap login yang berhasil maupun gagal, perubahan MFA, reset kata sandi, perubahan izin, penolakan kontrol akses, kegagalan validasi input, dan aksi admin, masing-masing dengan timestamp, ID pengguna, IP sumber, dan user agent.
Jangan pernah mencatat secret: kata sandi, token sesi, nomor kartu lengkap, API key. Samarkan di lapisan logging, bukan di setiap titik pemanggilan.
Kirim log keluar dari server ke penyimpanan terpusat (CloudWatch, Loki, Elastic, SIEM) dengan retensi minimal 90 hari, agar penyerang yang punya akses root tidak bisa menghapus jejaknya.
Pasang peringatan berdasarkan pola, bukan event tunggal: 50 login gagal dalam semenit, lonjakan 403 dari satu sesi, admin baru yang dibuat di luar jam kerja, sertifikat yang diterbitkan untuk domain Anda padahal tidak pernah Anda minta.
Fail closed: ketika pemeriksaan di hilir (layanan autentikasi, rate limiter, WAF) mengalami error, tolak request tersebut. A10 ada karena begitu banyak sistem justru memberikan akses ketika pemeriksaan yang seharusnya memblokir malah melempar exception.
Pantau dari luar: uptime, kedaluwarsa sertifikat, perubahan DNS, pencantuman di daftar blokir, dan regresi header. Pemeriksa Kesehatan Domain menggabungkan pemeriksaan DNS, SSL, autentikasi email, dan header ke dalam satu skor yang bisa Anda jalankan ulang setelah setiap deploy.
Tulis Rencana Respons Insiden Sebelum Anda Membutuhkannya
Tentukan sejak awal siapa yang siaga (on-call), cara merotasi setiap kredensial, cara mengubah situs menjadi read-only, di mana backup yang bersih disimpan, dan regulator atau pelanggan mana yang harus diberi tahu serta dalam berapa jam (72 jam menurut GDPR). Jalankan latihan tabletop setahun sekali. Tim dengan rencana yang sudah dilatih bisa pulih dalam hitungan hari; tim tanpa rencana berimprovisasi selama berminggu-minggu.
Uji: Scanner, Pentest, dan Pemeriksaan Berkelanjutan
Setiap kontrol di atas bisa diverifikasi, dan verifikasinya sebaiknya diotomatiskan sebisa mungkin agar tidak tergerus seiring waktu. Berikut tangga yang masuk akal, dari yang gratis dan instan hingga yang berkala dan berbayar:
| Pemeriksaan | Tool | Seberapa sering |
|---|---|---|
| Konfigurasi TLS, rantai sertifikat, masa berlaku | Pemeriksaan Sertifikat SSL, SSL Labs, testssl.sh | Setelah setiap perubahan sertifikat atau server; masa berlaku setiap hari |
| Security header dan CSP | Pemeriksaan Header HTTP, MDN HTTP Observatory | Setelah setiap deploy (masukkan ke CI) |
| Port terbuka | Pemeriksa Port, nmap | Setelah setiap perubahan firewall atau cloud |
| DNS, DNSSEC, autentikasi email | Pemeriksa Kesehatan Domain, Pemeriksa DMARC | Bulanan, dan setelah setiap perubahan DNS |
| Subdomain usang | Pencari Subdomain | Setiap kuartal dan setiap kali layanan dinonaktifkan |
| Dependensi yang diketahui rentan | npm audit, Dependabot, Trivy | Setiap build |
| Celah di level kode (SAST) | Semgrep, CodeQL | Setiap pull request |
| Kerentanan web saat runtime (DAST) | OWASP ZAP, Nuclei | Mingguan terhadap staging |
| Otorisasi dan logika bisnis | Penetration test manual atau program bug bounty | Tahunan, dan setelah fitur besar dirilis |
Scanner andal dalam menemukan injection, masalah header, dan komponen usang, tetapi lemah dalam otorisasi dan logika bisnis, jadi anggarkan setidaknya satu pengujian oleh manusia per tahun untuk apa pun yang menangani uang atau data pribadi. Perbaiki berdasarkan tingkat keterpaparan: apa pun yang bisa dieksploitasi pengguna tanpa autentikasi dari internet harus didahulukan.
Checklist Keamanan Website
Salin ini ke README proyek atau issue tracker Anda. Setiap baris adalah salah satu praktik di atas, dirumuskan agar bisa ditandai selesai atau belum; kolom terakhir adalah buktinya.
| Lapisan | Praktik | Selesai jika |
|---|---|---|
| Domain | Registrar lock dan MFA di akun registrar; perpanjangan otomatis aktif | WHOIS menampilkan clientTransferProhibited; masa berlaku masih lebih dari 12 bulan |
| DNS | Zona ditandatangani DNSSEC; record CAA hanya mencantumkan CA Anda | dig +dnssec mengembalikan RRSIG; record DS ada di zona induk |
| DNS | Tidak ada record CNAME atau A yang menggantung (dangling) | Setiap hostname dari Pencari Subdomain mengarah ke sesuatu yang Anda kendalikan |
| TLS | Hanya TLS 1.2+, TLS 1.3 diutamakan, rantai sertifikat lengkap disajikan | Pemeriksaan Sertifikat SSL: rantai lengkap, TLS 1.0/1.1 ditolak |
| TLS | HSTS dengan max-age satu tahun, includeSubDomains, sudah di-preload | Tercantum di hstspreload.org |
| TLS | Perpanjangan diotomatiskan lewat ACME; masa berlaku dipantau | certbot renew --dry-run berhasil; peringatan dipasang pada 14 hari |
| Header | CSP (berbasis nonce), frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy | Nilai A di Pemeriksaan Header HTTP |
| Autentikasi | Hashing Argon2id atau bcrypt; aturan kata sandi NIST; pemeriksaan daftar kebocoran | Satu hash memakan waktu 100 hingga 250 ms; tanpa aturan komposisi |
| Autentikasi | MFA ditawarkan ke semua pengguna, wajib untuk admin; passkey didukung | Login admin tidak mungkin tanpa faktor kedua |
| Autentikasi | Endpoint login, reset, dan MFA dibatasi rate limit per IP dan per akun | Percobaan keenam dalam satu menit mengembalikan 429 |
| Sesi | Cookie __Host- dengan Secure, HttpOnly, SameSite; ID dirotasi saat login | Atribut cookie terlihat di DevTools; sesi lama tidak valid setelah login |
| Input | Query berparameter di semua tempat; output di-encode sesuai konteks; upload divalidasi berdasarkan isinya | Tidak ada query hasil penyusunan string dalam pencarian kode; payload XSS tampil sebagai teks |
| Kontrol akses | Routing tolak-secara-default; pemeriksaan kepemilikan per objek; CORS ketat | Memutar ulang ID pengguna lain mengembalikan 404 atau 403 |
| Dependensi | Lockfile di-commit; npm ci; audit di CI; action di-pin ke SHA; SRI pada skrip CDN | Build gagal jika ada CVE dengan tingkat keparahan tinggi |
| Server | Hanya 80 dan 443 yang publik; SSH hanya dengan kunci; pembaruan keamanan otomatis; secret di env atau vault | Pemeriksa Port menunjukkan port 22, 3306, dan 6379 tertutup dari internet |
| Backup | 3-2-1 dengan satu salinan immutable; restore sudah diuji | Uji restore terakhir yang berhasil bertanggal dalam 90 hari terakhir |
SPF -all, DKIM, DMARC p=reject, MTA-STS | Lolos Pemeriksa DMARC; laporan agregat berdatangan | |
| Monitoring | Event autentikasi dan otorisasi dicatat secara terpusat; peringatan berbasis pola; pemantauan uptime, sertifikat, dan DNS dari luar | Peringatan uji sudah dipicu dan diterima |
| Respons | Rencana insiden tertulis; security.txt dipublikasikan; latihan tabletop sudah dijalankan | Rencana ditinjau dalam 12 bulan terakhir |
Pemetaan ke OWASP Top 10:2025
OWASP Top 10 adalah daftar risiko aplikasi web yang paling banyak dikutip, dan edisi 2025-nya mengubah urutan serta memperkenalkan dua kategori baru. Jika klien, auditor, atau framework kepatuhan menanyakan bagaimana Anda menanganinya, inilah pemetaannya ke praktik-praktik dalam panduan ini:
| OWASP Top 10:2025 | Praktik dalam panduan ini |
|---|---|
| A01 Broken Access Control | Tolak secara default, pemeriksaan per objek, CORS ketat, penguncian panel admin |
| A02 Security Misconfiguration | Security header, HSTS, port tertutup, header versi dihapus, directory listing dinonaktifkan |
| A03 Software Supply Chain Failures (baru) | Lockfile, audit, action yang di-pin, SRI, SBOM, CI dengan hak akses minimum |
| A04 Cryptographic Failures | TLS 1.2+ dan 1.3, HSTS, Argon2id, pengelolaan secret, backup terenkripsi |
| A05 Injection | Query berparameter, encoding output, CSP, validasi upload |
| A06 Insecure Design | Threat model per lapisan, default fail-closed, rate limiting sejak tahap desain |
| A07 Authentication Failures | Aturan kata sandi NIST, pemeriksaan kebocoran, MFA dan passkey, rotasi sesi |
| A08 Software or Data Integrity Failures | SRI, dependensi yang ditandatangani dan di-pin, deserialisasi yang aman |
| A09 Security Logging and Alerting Failures | Logging terpusat, peringatan berbasis pola, pemantauan eksternal |
| A10 Mishandling of Exceptional Conditions (baru) | Fail closed, respons error yang seragam, tanpa stack trace ke pengguna |
Cek security header situs Anda dalam hitungan detik
Pemeriksaan Header HTTP gratis dari DNS Robot mengambil URL apa pun dan menilai security header-nya dari A sampai F: HSTS, Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, dan Permissions-Policy, lengkap dengan nilai persis yang ditemukan dan apa yang belum ada. Tanpa perlu mendaftar.
Coba Pemeriksaan Header HTTPAdvertisement
FAQ Keamanan Website
Wajibkan HTTPS dengan TLS modern dan HSTS, kirim security header yang ketat (terutama Content Security Policy), hash kata sandi dengan Argon2id yang dilengkapi MFA dan rate limiting, gunakan query berparameter dan encoding output, terapkan kontrol akses di server untuk setiap objek, jaga dependensi tetap ter-patch dan di-pin, tutup port yang tidak dipakai, dan catat event keamanan secara terpusat. Kunci domain dan DNS terlebih dahulu, karena semua hal lain bergantung pada kendali Anda atas nama domain tersebut.