Keamanan Dimulai dari Pertanyaan, Bukan dari Alat
Menambahkan WAF, memasang pemindai, dan mengaktifkan semua header keamanan terasa produktif — tetapi tanpa memahami apa yang dilindungi dan dari siapa, usaha itu tersebar tipis di tempat yang salah. Pemodelan ancaman menjawab empat pertanyaan sederhana:
1. Apa yang kita bangun? → diagram alur data 2. Apa yang bisa salah? → daftar ancaman 3. Apa yang akan kita lakukan? → kontrol dan mitigasi 4. Apakah sudah cukup baik? → tinjau ulang dan ukur
STRIDE
Kerangka STRIDE membantu memunculkan ancaman secara sistematis alih-alih mengandalkan ingatan:
S Spoofing menyamar sebagai orang lain T Tampering mengubah data saat transit atau di penyimpanan R Repudiation menyangkal telah melakukan sesuatu I Information Disclosure membocorkan data ke pihak tak berhak D Denial of Service membuat layanan tidak tersedia E Elevation of Privilege memperoleh hak yang lebih tinggi
Terapkan pada setiap batas kepercayaan — tempat data berpindah dari zona dengan tingkat kepercayaan berbeda. Peramban ke API, API ke basis data, layanan ke layanan pihak ketiga.
Pertahanan Berlapis
Prinsipnya: asumsikan setiap lapis akan gagal. Bukan karena tim ceroboh, tetapi karena semua lapis pada akhirnya punya celah.
Jaringan firewall, segmentasi, TLS Gateway rate limit, WAF, validasi ukuran Aplikasi autentikasi, otorisasi, validasi input Data enkripsi, hak akses minimal, audit Operasi pemantauan, deteksi, tanggap insiden
Validasi JavaScript di peramban meningkatkan pengalaman pengguna — kesalahan terlihat sebelum permintaan dikirim. Tetapi penyerang tidak memakai peramban Anda; mereka memakai curl. Setiap validasi yang penting untuk keamanan harus diulang di server. Anggap sisi klien sebagai kenyamanan, bukan pertahanan.
Hak Akses Minimal
# Buruk — satu pengguna basis data untuk semuanya DATABASE_URL=postgres://admin:sandi@db/aplikasi # Lebih baik — hak sesuai kebutuhan tiap layanan GRANT SELECT, INSERT, UPDATE ON pesanan TO app_pesanan; GRANT SELECT ON produk TO app_katalog; REVOKE DELETE ON ALL TABLES IN SCHEMA public FROM app_katalog;
SQL injection pada akun dengan hak SELECT di satu tabel adalah insiden yang merepotkan. SQL injection yang sama pada akun superuser berarti seluruh basis data terekspos dan bisa dihapus. Celahnya identik — yang berbeda hanya batas kerusakannya.
Gagal Secara Tertutup
// Salah — kegagalan pemeriksaan membuka akses
try {
izin = await periksaIzin(pengguna, sumber);
} catch (e) {
izin = true; // "biar layanan tetap jalan"
}
// Benar — kegagalan berarti ditolak
try {
izin = await periksaIzin(pengguna, sumber);
} catch (e) {
log.error({ e }, "pemeriksaan izin gagal");
throw new GalatOtorisasi("tidak dapat memverifikasi izin");
}
Ketika layanan otorisasi bermasalah, godaan untuk "sementara meloloskan permintaan agar tidak mengganggu pengguna" sangat besar. Tetapi itu berarti siapa pun yang mampu membuat layanan otorisasi tidak responsif — bahkan sekadar membanjirinya — otomatis memperoleh akses penuh. Ketidaktersediaan yang jujur jauh lebih baik daripada otorisasi yang diam-diam mati.