Sampul buku
SEC-OPS · APPSEC HANDBOOK
STATUS: HARDENING · v1.0
Keamanan Aplikasi & Data

Bikin App yang Aman

Siap Dijual & Tahan Serangan

Dari model ancaman sampai incident response — panduan praktis membangun perangkat lunak yang layak dipercaya pelanggan, lolos audit, dan tidak jebol di malam pertama rilis.

Edisi Pertama · 2026 · Bahasa Indonesia
◆ 16 BAB · ALAT AUDIT INTERAKTIF · SIAP-SALIN
Sec-Ops · AppSec Handbook · v1.0

Keamanan Aplikasi & Data

Bikin App yang Aman, Siap Dijual & Tahan Serangan. Sebuah manual praktik untuk pengembang, arsitek, dan pemilik produk — dari nol sampai siap audit.

Front Matter

Prakata

// sec-ops/00_prakata

Setiap baris kode yang Anda tulis adalah janji. Janji bahwa nama, kata sandi, riwayat transaksi, dan rahasia kecil pengguna akan Anda jaga. Ketika aplikasi bocor, yang runtuh bukan sekadar server — melainkan kepercayaan, dan kepercayaan tidak punya tombol "restore from backup".

Buku ini lahir dari sebuah kegelisahan sederhana. Terlalu banyak aplikasi yang jalan tetapi tidak aman. Fitur lengkap, tampilan mulus, demo memukau — lalu jebol di minggu pertama karena satu kolom yang tidak divalidasi, satu password yang disimpan sebagai teks polos, atau satu kunci API yang lupa dicabut dari repositori publik. Keamanan sering diperlakukan sebagai lapisan cat yang dioleskan di akhir, padahal ia adalah rangka bangunan.

Saya menulis buku ini untuk semua level. Jika Anda baru mulai, setiap bab dimulai dari intuisi dan analogi sebelum masuk ke kode. Jika Anda sudah berpengalaman, ada tabel keputusan, potongan kode siap-salin, dan daftar periksa yang bisa langsung Anda tempel ke pipeline. Dan karena zaman sudah berubah, buku ini juga ditulis agar bisa dibaca oleh AI: judul terstruktur, langkah eksplisit, dan satu bab khusus tentang cara asisten AI sebaiknya memakai isi buku ini.

Keamanan adalah sebuah proses, bukan sebuah produk.

Bruce Schneier, kriptografer

Tidak ada aplikasi yang 100% aman. Tujuan kita bukan kesempurnaan mustahil, melainkan menaikkan biaya serangan setinggi mungkin sambil menurunkan dampak bila serangan berhasil. Itulah inti dari pertahanan berlapis. Selamat membaca, dan selamat membangun sesuatu yang layak dipercaya.

— Galih Prasetyo, 2026

Front Matter

Cara Membaca Buku Ini

// sec-ops/00_howto

Buku ini terbagi menjadi 16 bab yang bisa dibaca berurutan atau melompat sesuai kebutuhan. Namun ada urutan logis yang saya sarankan.

Tiga cara memakai buku ini

◆ Konvensi kode

Contoh kode memakai Node.js/JavaScript, SQL, dan shell sebagai bahasa lingua-franca karena paling mudah dibaca lintas-ekosistem. Prinsipnya berlaku universal — terjemahkan ke Python, Go, PHP, Java, atau bahasa apa pun yang Anda pakai. Setiap blok kode punya tombol Salin.

Peta perjalanan

BagianBabYang Anda dapat
Fondasi1–2Kenapa keamanan wajib, dan cara berpikir seperti penyerang (model ancaman).
Kripto & Kredensial3–5Enkripsi, hashing password, dan mengelola secret tanpa bocor.
Identitas & Akses6–8Autentikasi, otorisasi/RBAC, serta perlindungan data pribadi & UU PDP.
Pertahanan Aplikasi9–13OWASP Top 10, validasi input, rate limit, logging, dan rantai pasok.
Operasi & Penutup14–16Incident response, cara dibaca AI, FAQ, glosarium, checklist.
Front Matter

Notasi & Simbol

// sec-ops/00_notasi

Agar cepat dipindai (oleh manusia maupun AI), buku ini memakai kotak-kotak penanda yang konsisten. Inilah artinya.

⚠ Bahaya

Praktik berbahaya atau anti-pola yang harus Anda hindari. Jika Anda melihat ini di kode Anda, perbaiki segera.

▲ Hati-hati

Ada nuansa, jebakan umum, atau trade-off yang perlu dipertimbangkan sebelum menerapkan.

✓ Praktik Baik

Rekomendasi yang bisa Anda jadikan default. Aman untuk disalin.

◆ Catatan

Konteks tambahan, definisi, atau penjelasan "kenapa begini".

Simbol tingkat prioritas dalam checklist: [P0] wajib sebelum rilis, [P1] penting, [P2] peningkatan. Bobot pada Alat Audit ditulis ×N (semakin besar N, semakin kritikal).

Bab 01

Pendahuluan: Kenapa Keamanan Wajib untuk App yang Dijual

// sec-ops/01_intro

Bayangkan Anda baru saja menutup penjualan pertama. Pelanggan menandatangani kontrak, memasukkan data karyawan mereka ke aplikasi Anda, dan mulai bergantung padanya untuk operasional harian. Tiga bulan kemudian, sebuah email masuk: "Data kami muncul di forum internet. Bagaimana ini bisa terjadi?" Momen itu — bukan momen peluncuran — adalah ujian sesungguhnya dari perangkat lunak Anda.

Ada perbedaan mendasar antara aplikasi hobi dan aplikasi yang dijual. Aplikasi hobi hanya menanggung risiko diri sendiri. Aplikasi yang dijual menanggung risiko orang lain — dan itu memikul kewajiban hukum, finansial, dan moral. Ketika uang berpindah tangan, ekspektasi keamanan naik drastis, entah tertulis di kontrak atau tidak.

Keamanan sebagai fitur yang tak terlihat

Pengguna tidak pernah memuji Anda karena data mereka aman — itu dianggap sudah semestinya. Tetapi mereka akan meninggalkan Anda dalam sekejap ketika data itu bocor. Keamanan adalah fitur yang hanya terlihat ketika ia gagal. Inilah paradoks yang membuatnya sering diabaikan: karena tidak menghasilkan "wow" di demo, ia mudah dikorbankan demi tenggat.

Padahal secara bisnis, keamanan justru membuka penjualan. Perusahaan menengah dan besar akan menanyakan: apakah data terenkripsi? Apakah ada audit trail? Bagaimana Anda menangani insiden? Tanpa jawaban meyakinkan, Anda tersingkir dari tender bahkan sebelum bicara harga. Keamanan yang baik adalah kompetitif.

Hanya ada dua jenis perusahaan: yang sudah diretas, dan yang belum tahu bahwa mereka sudah diretas.

Robert S. Mueller III, mantan Direktur FBI (RSA Conference, 2012)

Biaya sebuah kebocoran

Mari kita jujur soal angka. Sebuah insiden kebocoran data bukan hanya soal "memperbaiki bug". Biayanya berlapis:

Jenis BiayaContoh Konkret
LangsungInvestigasi forensik, perbaikan darurat, lembur tim, konsultan keamanan.
RegulasiDenda UU PDP (Indonesia), notifikasi wajib ke otoritas & korban dalam tenggat.
ReputasiPelanggan berhenti berlangganan, calon pembeli mundur, liputan media negatif.
HukumGugatan class action, klausul ganti rugi di kontrak korporat.
OperasionalLayanan down saat penanganan, kehilangan momentum produk, moral tim turun.

Bandingkan itu dengan biaya mencegah: beberapa hari kerja untuk hashing yang benar, validasi input, dan konfigurasi TLS. Rasio untung-rugi pencegahan hampir selalu berpihak pada Anda. Keamanan adalah asuransi termurah yang bisa Anda beli dengan disiplin, bukan uang.

Tiga pilar yang harus Anda ingat

Seluruh buku ini pada dasarnya melayani tiga tujuan klasik yang disingkat CIA — bukan agen rahasia, tapi tiga sifat data yang harus dijaga:

Confidentiality hanya yang berhak Integrity tak diubah diam-diam Availability selalu tersedia Segitiga CIA — fondasi setiap keputusan keamanan
Gambar 1.1 — Tiga sifat data yang harus dijaga secara seimbang.

Pola pikir: pertahanan berlapis

Prinsip terpenting yang akan berulang di seluruh buku ini adalah defense in depth — pertahanan berlapis. Jangan pernah bergantung pada satu kontrol. Firewall bisa salah konfigurasi, validasi bisa terlewat, pustaka bisa punya celah. Dengan berlapis, kegagalan satu lapisan tidak langsung menjadi bencana.

✓ Prinsip inti

Asumsikan setiap lapisan bisa gagal. Rancang agar kegagalan satu kontrol tidak berarti kompromi total. Tambahkan prinsip least privilege (beri hak seminimal mungkin) dan secure by default (default-nya aman, bukan default-nya terbuka).

Sepuluh prinsip keamanan abadi

Teknologi berubah setiap tahun, tetapi prinsip di bawah ini bertahan puluhan tahun. Jadikan ia lensa untuk menilai keputusan apa pun — bila sebuah desain melanggar salah satunya, berhentilah dan pikirkan ulang.

#PrinsipArtinya dalam praktik
1Least PrivilegeBeri hak seminimal yang diperlukan, tidak lebih. Cabut yang tak dipakai.
2Defense in DepthBanyak lapisan; satu gagal, yang lain menahan.
3Fail SecurelySaat error, default ke menolak akses — bukan membukanya.
4Secure by DefaultKonfigurasi bawaan harus aman tanpa perlu diutak-atik.
5Minimize Attack SurfaceKurangi fitur, port, endpoint, dan data yang terekspos.
6Don't Trust InputValidasi semua yang datang dari luar batas kepercayaan.
7Complete MediationCek otorisasi pada setiap akses, bukan sekali di awal.
8Separation of DutiesPisahkan peran kritis agar tak ada satu titik kuasa mutlak.
9Keep It SimpleKompleksitas melahirkan celah; kesederhanaan bisa diaudit.
10Assume BreachRancang untuk membatasi dampak ketika — bukan jika — jebol.

Ada dua cara merancang sistem: begitu sederhana sehingga jelas tak ada kekurangan, atau begitu rumit sehingga tak ada kekurangan yang jelas.

C.A.R. Hoare, ilmuwan komputer (kuliah Turing Award, 1980)

Sebelum kita menyelam ke bab-bab teknis, mari lakukan pemeriksaan cepat. Alat berikut membantu Anda memetakan posisi keamanan aplikasi Anda saat ini. Centang apa yang sudah Anda lakukan; skor per kategori dan verdict akan muncul secara langsung. Ini akan menjadi peta bacaan Anda: kategori berskor rendah menunjukkan bab mana yang paling mendesak untuk Anda baca.

◆ Alat: Audit Keamanan Interaktif

Centang setiap kontrol yang sudah benar-benar Anda terapkan (bukan yang "rencananya"). Setiap butir punya bobot sesuai tingkat kritikalitasnya. Gunakan tombol Contoh untuk melihat simulasi, dan Reset untuk mengosongkan.

Security Posture Audit

RENTAN

Ambang verdict: <50% Rentan · 50–79% Cukup · ≥80% Aman. Semua perhitungan berjalan lokal di browser Anda; tidak ada data yang dikirim ke mana pun.

Bab 02

Model Ancaman: Berpikir Seperti Penyerang

// sec-ops/02_threat_model

Anda tidak bisa mempertahankan sesuatu yang tidak Anda pahami cara menyerangnya. Model ancaman (threat modeling) adalah latihan terstruktur untuk bertanya: apa yang berharga, siapa yang mengincarnya, lewat mana mereka masuk, dan apa yang terjadi bila mereka berhasil. Ini adalah bab paling murah dan paling berdampak dalam buku ini, karena hanya butuh papan tulis dan kejujuran.

Empat pertanyaan inti

Kerangka Shostack menyederhanakan threat modeling menjadi empat pertanyaan yang bisa Anda tanyakan pada tim mana pun:

  1. Apa yang sedang kita bangun? Gambarkan sistem: komponen, aliran data, batas kepercayaan (trust boundary).
  2. Apa yang bisa salah? Enumerasi ancaman terhadap tiap komponen dan aliran.
  3. Apa yang akan kita lakukan soal itu? Tentukan mitigasi untuk ancaman yang penting.
  4. Apakah kita sudah melakukannya dengan baik? Validasi dan ulangi secara berkala.

Aset, aktor, dan permukaan serangan

Mulai dengan mendaftar tiga hal. Aset: apa yang berharga (kredensial, data pribadi, kunci, dana, reputasi). Aktor ancaman: siapa yang mungkin menyerang. Permukaan serangan (attack surface): setiap titik di mana data masuk atau keluar sistem — form, API, upload file, webhook, integrasi pihak ketiga.

Aktor AncamanMotivasiKemampuan
Skrip otomatis / botCari korban acak, spam, kredensial dumpingRendah, tapi masif & terus-menerus
Penyerang oportunistikUang cepat, ransomware, penjualan dataMenengah, memakai exploit publik
Orang dalam (insider)Dendam, keuntungan, kelalaianAkses sah — sangat berbahaya
Pesaing / mata-mata industriRahasia dagang, sabotaseMenengah–tinggi, bertarget
Aktor negara (APT)Spionase, disrupsiTinggi, sabar, sumber daya besar
▲ Jangan lupakan insider

Statistik industri konsisten menunjukkan sebagian besar insiden melibatkan faktor internal — entah jahat, entah lalai. Prinsip least privilege dan audit trail (Bab 12) adalah pertahanan utama Anda di sini, bukan firewall.

STRIDE: taksonomi ancaman

STRIDE adalah akronim dari Microsoft untuk mengklasifikasikan enam jenis ancaman. Gunakan sebagai daftar periksa untuk setiap komponen sistem.

HurufAncamanMelanggarContoh
SSpoofing (pemalsuan identitas)AutentikasiLogin sebagai orang lain, sesi dicuri
TTampering (perusakan data)IntegritasUbah harga di keranjang, manipulasi request
RRepudiation (penyangkalan)Non-repudiation"Bukan saya yang transfer" tanpa jejak
IInformation DisclosureKerahasiaanKebocoran data, error yang bocorkan detail
DDenial of ServiceKetersediaanBanjir request, query mahal
EElevation of PrivilegeOtorisasiUser biasa jadi admin

Contoh nyata: memodelkan endpoint login

Mari terapkan STRIDE pada satu endpoint POST /login. Perhatikan betapa banyak ancaman muncul dari satu titik masuk sederhana.

threat-model
# Endpoint: POST /login  (email + password)
# Aset: kredensial pengguna, sesi, akun

Spoofing         -> credential stuffing, brute force
                    Mitigasi: rate limit, MFA, cek password bocor
Tampering        -> ubah payload, mass assignment role=admin
                    Mitigasi: validasi allowlist field, abaikan field tak dikenal
Repudiation      -> tidak ada bukti percobaan login
                    Mitigasi: audit log (ip, ua, waktu, hasil)
Info Disclosure  -> pesan "email tidak ada" bocorkan akun valid
                    Mitigasi: pesan error generik "email/password salah"
DoS              -> hash password mahal dipakai untuk DoS
                    Mitigasi: rate limit sebelum hashing, captcha adaptif
Elevation        -> respons login sertakan token beroverprivilege
                    Mitigasi: scope minimal, klaim diverifikasi server-side

Kompleksitas adalah musuh terburuk keamanan. Sistem yang rumit lebih sulit dipahami, lebih sulit dianalisis, dan lebih mudah dieksploitasi.

Bruce Schneier

Diagram aliran data & batas kepercayaan

Gambar sederhana lebih berharga daripada dokumen 20 halaman. Petakan komponen dan tarik garis merah di setiap batas kepercayaan — tempat data berpindah dari zona yang kurang tepercaya ke yang lebih tepercaya. Di garis merah itulah validasi dan otorisasi harus terjadi.

Browser APIvalidasi+authz Database Pihak-3SSRF risk TRUST BOUNDARY
Gambar 2.1 — Garis putus merah = batas kepercayaan. Di situlah kontrol keamanan wajib berdiri.
✓ Ringkasan bab

Luangkan satu jam bersama tim sebelum menulis fitur besar. Gambar sistemnya, jalankan STRIDE, catat mitigasi. Model ancaman bukan dokumen sekali jadi — perbarui setiap kali arsitektur berubah. Investasi kecil ini mencegah kelas kesalahan yang mahal.

Bab 03

Enkripsi: At-Rest, In-Transit, dan Kunci

// sec-ops/03_encryption

Enkripsi mengubah data yang bisa dibaca menjadi sandi yang tak berarti tanpa kunci yang benar. Ia adalah lapisan terakhir yang melindungi Anda: bahkan bila penyerang berhasil mencuri hard disk atau menyadap jaringan, data terenkripsi tetap tak berguna bagi mereka. Namun enkripsi hanya sekuat pengelolaan kuncinya — dan di situlah kebanyakan orang tersandung.

Kriptografi biasanya di-bypass, bukan ditembus.

Adi Shamir, salah satu penemu algoritma RSA

Kalimat Shamir di atas adalah pelajaran terpenting bab ini. Penyerang jarang memecahkan AES-256 secara matematis — itu praktis mustahil. Mereka mencari kunci yang tersimpan sembarangan, konfigurasi TLS yang salah, atau data yang lupa dienkripsi. Fokus Anda bukan memilih algoritma paling eksotis, melainkan menerapkan yang standar dengan benar.

⚠ Aturan emas kriptografi

Jangan pernah membuat algoritma kripto sendiri. Gunakan pustaka standar yang telah diaudit (libsodium, Web Crypto API, penyedia KMS). Kriptografi buatan sendiri hampir pasti punya celah yang tak Anda sadari. "Roll your own crypto" adalah anti-pola nomor satu.

Dua keadaan data

Data hidup di dua keadaan yang butuh perlindungan berbeda:

(Ada keadaan ketiga, in-use — data di memori saat diproses — yang dilindungi teknik lanjutan seperti enkripsi homomorfik dan enclave. Untuk mayoritas aplikasi, fokuslah pada dua yang pertama dulu.)

In-transit: TLS yang benar

TLS (dulu SSL) mengenkripsi lalu lintas jaringan dan memverifikasi identitas server lewat sertifikat. Ini tidak opsional untuk aplikasi apa pun yang menyentuh internet.

✓ Checklist TLS

[P0] Paksa TLS 1.2 atau 1.3, nonaktifkan protokol lama (SSLv3, TLS 1.0/1.1). [P0] Redirect semua HTTP ke HTTPS. [P0] Aktifkan HSTS agar browser menolak koneksi tak-terenkripsi. [P1] Gunakan sertifikat otomatis (Let's Encrypt) agar tak pernah kedaluwarsa diam-diam.

nginx
# Konfigurasi TLS modern + HSTS + redirect
server {
  listen 80;
  server_name app.contoh.id;
  return 301 https://$host$request_uri;   # paksa HTTPS
}
server {
  listen 443 ssl http2;
  server_name app.contoh.id;

  ssl_protocols TLSv1.2 TLSv1.3;           # tolak yang lama
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;

  # HSTS: 2 tahun, termasuk subdomain
  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
}

At-rest: mengenkripsi penyimpanan

Ada dua level. Enkripsi seluruh disk/volume (mis. fitur bawaan cloud) melindungi dari pencurian fisik disk, tetapi tidak dari aplikasi yang dibobol — karena bagi aplikasi, data terlihat normal. Enkripsi level aplikasi/kolom mengenkripsi field sensitif tertentu (NIK, nomor rekening) sebelum masuk database, sehingga bahkan admin database tidak bisa membacanya.

▲ Pilih yang tepat untuk data yang tepat

Jangan enkripsi kolom yang perlu di-query (WHERE, JOIN, sort) tanpa strategi khusus — hasilnya jadi acak dan tak bisa dicari. Enkripsi kolom cocok untuk data yang disimpan dan ditampilkan utuh (nomor kartu, dokumen), bukan untuk yang harus difilter di database.

AEAD: enkripsi yang benar di 2026

Gunakan mode AEAD (Authenticated Encryption with Associated Data) seperti AES-256-GCM atau XChaCha20-Poly1305. AEAD mengenkripsi dan mendeteksi kalau ciphertext diubah — melindungi kerahasiaan sekaligus integritas sekaligus. Setiap operasi enkripsi wajib memakai nonce/IV yang unik.

node.js
const crypto = require('crypto');

// key: 32 byte dari KMS/vault — JANGAN hardcode
function encrypt(plaintext, key) {
  const iv = crypto.randomBytes(12);          // nonce unik per pesan
  const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
  const enc = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
  const tag = cipher.getAuthTag();          // tag integritas
  return Buffer.concat([iv, tag, enc]).toString('base64');
}

function decrypt(blob, key) {
  const raw = Buffer.from(blob, 'base64');
  const iv = raw.subarray(0, 12), tag = raw.subarray(12, 28), data = raw.subarray(28);
  const d = crypto.createDecipheriv('aes-256-gcm', key, iv);
  d.setAuthTag(tag);                          // gagal jika diubah
  return Buffer.concat([d.update(data), d.final()]).toString('utf8');
}

Manajemen kunci: bagian yang benar-benar sulit

Kunci enkripsi adalah "kunci dari segala kunci". Bila ia bocor, seluruh enkripsi runtuh. Bila ia hilang, data Anda hilang selamanya. Prinsip-prinsip berikut wajib:

PrinsipPenjelasan
Pisahkan kunci dari dataKunci tidak boleh tinggal di tempat yang sama dengan data terenkripsi. Simpan di KMS/HSM/vault.
Envelope encryptionData dienkripsi dengan Data Key; Data Key dienkripsi dengan Master Key di KMS. Rotasi jadi mudah.
Rotasi berkalaGanti kunci secara terjadwal dan setelah insiden. Simpan versi kunci agar data lama tetap terbaca.
Least privilegeHanya layanan yang perlu yang boleh memakai kunci. Catat setiap penggunaan kunci (audit).
Backup kunciKehilangan kunci = kehilangan data. Backup terpisah & teruji, dengan kontrol akses ketat.
◆ KMS vs Vault vs .env

Untuk produksi serius, gunakan layanan kunci terkelola (AWS KMS, Google Cloud KMS, Azure Key Vault) atau HashiCorp Vault. File .env boleh untuk konfigurasi non-kritis di tahap awal, tetapi kunci enkripsi utama sebaiknya tidak pernah hidup sebagai teks polos di disk. Lihat Bab 5 untuk detail manajemen secrets.

Hashing bukan enkripsi

Kesalahpahaman paling umum: mengira password perlu "dienkripsi". Salah. Enkripsi bisa dibalik (ada dekripsi); password tidak boleh bisa dibalik. Untuk password, kita memakai hashing satu arah — topik Bab 4 berikutnya. Ingat perbedaan ini baik-baik: enkripsi untuk data yang perlu dibaca kembali, hashing untuk verifikasi tanpa menyimpan aslinya.

Bab 04

Hashing Password: Argon2, bcrypt, Salt & Pepper

// sec-ops/04_password_hash

Jika hanya satu bab yang Anda baca, jadikan ini bab itu. Cara Anda menyimpan password adalah pembeda paling telak antara aplikasi amatir dan profesional. Kabar baiknya: melakukannya dengan benar hanya butuh beberapa baris kode dan satu pustaka yang tepat.

⚠ Yang TIDAK boleh, selamanya

Jangan simpan password sebagai teks polos. Jangan pakai MD5 atau SHA-1/SHA-256 polos untuk password. Jangan pakai enkripsi dua arah. Jangan buat skema hashing sendiri. Semua ini bisa dipecahkan dalam hitungan detik oleh GPU modern atau tabel rainbow.

Kenapa hash cepat justru buruk

SHA-256 dirancang untuk cepat — itu bagus untuk verifikasi file, buruk untuk password. GPU modern bisa menghitung miliaran hash SHA-256 per detik. Artinya, jika database Anda bocor, penyerang bisa menebak password lemah hampir seketika. Untuk password kita justru butuh algoritma yang sengaja lambat dan haus memori, sehingga menebak jadi mahal.

Password itu seperti pakaian dalam: jangan biarkan orang melihatnya, ganti secara berkala, dan jangan berbagi dengan orang asing.

Pepatah keamanan (dipopulerkan Chris Pirillo)

Algoritma pilihan

AlgoritmaStatusKapan dipakai
Argon2id★ Rekomendasi utamaPemenang Password Hashing Competition. Tahan GPU & ASIC. Pilihan pertama untuk proyek baru.
scryptBaikHaus memori, alternatif solid bila Argon2 tak tersedia.
bcryptBaik, teruji waktuSangat matang & tersedia di mana-mana. Batas 72 byte input. Aman bila Argon2 belum ada.
PBKDF2Boleh (jika wajib)Sering diwajibkan standar kepatuhan (FIPS). Pakai iterasi tinggi.
MD5, SHA-* polos✗ JanganTerlalu cepat. Tidak pernah untuk password.

Salt: melumpuhkan rainbow table

Salt adalah nilai acak unik untuk setiap password, digabung sebelum hashing. Dampaknya besar: dua pengguna dengan password sama akan punya hash berbeda, dan tabel rainbow (hash yang sudah dihitung sebelumnya) jadi tak berguna. Kabar baik: pustaka modern seperti Argon2 dan bcrypt menghasilkan dan menyimpan salt otomatis di dalam string hash. Anda tak perlu mengelolanya manual.

node.js — argon2
const argon2 = require('argon2');

// Saat registrasi / ganti password
async function hashPassword(plain) {
  return argon2.hash(plain, {
    type: argon2.argon2id,   // varian yang direkomendasikan
    memoryCost: 19456,       // ~19 MB, setel sesuai server
    timeCost: 2,
    parallelism: 1
  });
  // hasil sudah termasuk salt + parameter, simpan apa adanya
}

// Saat login
async function verifyPassword(hash, plain) {
  try { return await argon2.verify(hash, plain); }
  catch { return false; }
}
node.js — bcrypt
const bcrypt = require('bcrypt');
const ROUNDS = 12;                 // cost factor, naikkan seiring waktu

const hash = await bcrypt.hash(plain, ROUNDS);   // salt otomatis
const ok   = await bcrypt.compare(plain, hash);

Pepper: lapisan ekstra

Pepper adalah rahasia tambahan yang sama untuk semua password, tetapi — dan ini kuncinya — tidak disimpan di database. Ia hidup di secrets manager/HSM. Bila database bocor tetapi pepper tidak, penyerang tetap tak bisa memecahkan hash. Terapkan pepper sebagai HMAC sebelum hashing, atau sebagai enkripsi pada hash hasil.

▲ Pepper itu opsional, salt itu wajib

Salt sudah ditangani pustaka dan wajib. Pepper adalah pertahanan-berlapis tambahan yang berguna jika Anda bisa mengelola secret terpisah dengan aman. Jangan menukar salt dengan pepper — keduanya melayani tujuan berbeda.

Kebijakan password yang manusiawi

Pedoman modern (NIST 800-63B) mengubah nasihat lama. Yang benar sekarang:

Migrasi tanpa downtime

Punya database lama dengan hash usang (mis. SHA-1)? Jangan menunggu semua pengguna login untuk migrasi. Pakai strategi rehash saat login: saat pengguna login dan verifikasi berhasil, jika hash-nya format lama, hitung ulang dengan Argon2 dan simpan. Untuk yang belum pernah login, bungkus hash lama di dalam Argon2 (hash-of-hash) agar tetap terlindungi selama transisi.

✓ Ringkasan bab

Pakai Argon2id (atau bcrypt cost≥12). Biarkan pustaka mengurus salt. Tambah pepper bila mampu. Cek password terhadap daftar bocor. Naikkan parameter biaya seiring perangkat keras makin cepat. Dengan ini, kebocoran database bukan lagi bencana total bagi kredensial pengguna Anda.

Bab 05

Manajemen Secrets: Jangan Pernah Hardcode

// sec-ops/05_secrets

Secret adalah setiap nilai rahasia yang memberi akses: password database, kunci API, token, kunci enkripsi, kredensial pihak ketiga. Satu secret yang bocor bisa membuka seluruh sistem Anda. Ironisnya, kebocoran secret paling sering bukan karena serangan canggih, melainkan karena secret ditulis di tempat yang salah — di dalam kode, lalu di-commit ke Git.

⚠ Dosa besar: secret di repositori

Begitu secret masuk ke Git, ia ada di seluruh riwayat selamanya, di setiap klon, di setiap fork. Menghapusnya di commit berikutnya tidak cukup. Bot memindai GitHub publik untuk kunci API dalam hitungan detik setelah di-push. Anggap secret yang pernah masuk Git sebagai sudah bocor — cabut dan ganti segera.

Hierarki tempat menyimpan secret

CaraKeamananCocok untuk
Hardcode di kode✗ TerburukTidak pernah.
File .env (di-gitignore)DasarDev lokal, proyek kecil. Jangan di-commit.
Env var dari platformLumayanDeploy PaaS, container. Injeksi saat runtime.
Secrets manager★ BaikProduksi. Vault, AWS/GCP/Azure Secrets Manager.
HSM / KMSTerbaikKunci kripto & secret paling kritis.

Pola dasar: baca dari environment

node.js
// config.js — satu tempat, validasi saat boot
function required(name) {
  const v = process.env[name];
  if (!v) throw new Error(`Secret hilang: ${name}`); // fail fast
  return v;
}

module.exports = {
  dbUrl:     required('DATABASE_URL'),
  jwtSecret: required('JWT_SECRET'),
  apiKey:    required('PAYMENT_API_KEY'),
};
// JANGAN: const apiKey = "sk_live_51H..." (hardcoded)
gitignore
# Pastikan file secret tak pernah ikut ter-commit
.env
.env.*
!.env.example        # template TANPA nilai asli boleh di-commit
*.pem
*.key
secrets/
◆ Selalu sediakan .env.example

Commit sebuah .env.example yang berisi nama variabel dengan nilai kosong atau placeholder jelas (DATABASE_URL=). Ini mendokumentasikan konfigurasi yang dibutuhkan tanpa membocorkan nilai asli, dan memudahkan anggota tim baru.

Secrets manager untuk produksi

Di produksi, jangan simpan secret sebagai teks di disk. Gunakan secrets manager yang: menyimpan terenkripsi, mengontrol siapa yang boleh mengakses, mencatat setiap akses (audit), dan mendukung rotasi. Aplikasi meminta secret saat runtime lewat identitas layanan (IAM role), bukan lewat kredensial statis.

node.js — vault pattern
// Ambil secret saat boot dari manager (pseudo, pola umum)
async function loadSecrets() {
  const client = makeSecretsClient({ region: process.env.REGION });
  const [db, jwt] = await Promise.all([
    client.get('prod/database_url'),
    client.get('prod/jwt_secret'),
  ]);
  return { dbUrl: db, jwtSecret: jwt };
}
// Akses diberikan lewat IAM role instance — tanpa kunci statis

Rotasi & deteksi kebocoran

bash — pre-commit
# .git/hooks/pre-commit — cegah secret ter-commit
if gitleaks protect --staged --no-banner; then
  echo "✓ Tidak ada secret terdeteksi"
else
  echo "✗ Secret terdeteksi — commit dibatalkan"
  exit 1
fi

Amatir meretas sistem; profesional meretas manusia. Dan cara termudah meretas manusia adalah menunggu mereka menaruh kunci di bawah keset.

Bruce Schneier (parafrasa)
✓ Ringkasan bab

Nol secret di kode. .env di-gitignore untuk dev, secrets manager untuk produksi. Validasi keberadaan secret saat boot (fail fast). Pasang scanner di CI/pre-commit. Rotasi berkala, dan perlakukan secret yang pernah menyentuh Git sebagai sudah bocor.

Bab 06

Autentikasi: Session, JWT, OAuth, 2FA, Magic Link

// sec-ops/06_authentication

Autentikasi menjawab pertanyaan "siapa Anda?". Ini gerbang depan aplikasi Anda, dan karenanya target favorit penyerang. Bab ini membedah cara membuktikan identitas dan menjaga sesi tetap aman — beserta jebakan di setiap pendekatan.

◆ Authn vs Authz

Autentikasi (authn) = membuktikan siapa Anda. Otorisasi (authz) = menentukan apa yang boleh Anda lakukan. Keduanya sering tertukar. Bab ini soal authn; Bab 7 soal authz. Jangan pernah menyimpulkan izin hanya dari fakta bahwa seseorang sudah login.

Faktor autentikasi

Identitas dibuktikan lewat satu atau lebih faktor: sesuatu yang Anda tahu (password), sesuatu yang Anda punya (ponsel, kunci keamanan), sesuatu yang Anda adalah (biometrik). Menggabungkan dua faktor berbeda = Two-Factor Authentication (2FA), dan ini menaikkan keamanan secara dramatis.

Session vs JWT: dua model besar

AspekSession (stateful)JWT (stateless)
Cara kerjaID sesi acak di cookie; data di serverToken bertanda-tangan berisi klaim; disimpan klien
Revoke/logoutMudah — hapus di serverSulit — token valid sampai kedaluwarsa
Skala horizontalButuh store bersama (Redis)Tak perlu store (verifikasi tanda tangan)
UkuranKecil (hanya ID)Lebih besar (bawa klaim)
Cocok untukWeb app tradisional, kontrol ketatAPI, microservices, mobile
▲ JWT bukan peluru perak

Kesulitan me-revoke JWT adalah kelemahan nyata. Solusi umum: buat access token berumur pendek (5–15 menit) + refresh token berumur panjang yang bisa dicabut & disimpan server. Jangan simpan data sensitif di payload JWT — ia hanya di-encode base64, bukan dienkripsi, dan bisa dibaca siapa saja.

Cookie sesi yang aman

Apa pun modelnya, jika Anda menaruhnya di cookie, setel flag-nya dengan benar:

node.js — cookie
res.cookie('sid', sessionId, {
  httpOnly: true,     // JS klien tak bisa baca -> tahan XSS mencuri sesi
  secure:   true,     // hanya via HTTPS
  sameSite: 'lax',    // mitigasi CSRF (atau 'strict')
  maxAge:   1000 * 60 * 60 * 8,   // 8 jam
  path:     '/'
});

JWT yang benar

node.js — jwt
const jwt = require('jsonwebtoken');

// Terbitkan access token pendek
const access = jwt.sign(
  { sub: user.id, role: user.role },
  process.env.JWT_SECRET,
  { expiresIn: '15m', issuer: 'app.contoh.id', algorithm: 'HS256' }
);

// Verifikasi — WAJIB kunci algoritma agar tak kena serangan alg=none
try {
  const claims = jwt.verify(token, process.env.JWT_SECRET, {
    algorithms: ['HS256'], issuer: 'app.contoh.id'
  });
} catch (e) { /* tolak: kedaluwarsa/tanda tangan salah */ }
⚠ Serangan alg=none

Beberapa pustaka JWT lawas menerima token dengan header alg: none (tanpa tanda tangan). Penyerang bisa memalsukan token apa pun. Selalu tetapkan daftar algoritma yang diizinkan saat verifikasi, dan jangan pernah memakai kunci publik sebagai kunci HMAC.

OAuth 2.0 & "Login dengan..."

OAuth 2.0 memungkinkan pengguna login lewat penyedia (Google, GitHub) tanpa Anda pernah menyentuh password mereka. Untuk aplikasi web/mobile, gunakan alur Authorization Code + PKCE. Jangan pakai Implicit flow (usang). Selalu validasi parameter state untuk mencegah CSRF, dan verifikasi id_token bila memakai OpenID Connect.

◆ OAuth ≠ autentikasi murni

OAuth aslinya untuk otorisasi delegasi (akses ke sumber daya). Untuk "login sebagai identitas", gunakan lapisan OpenID Connect (OIDC) di atas OAuth. Jangan gunakan access token sebagai bukti identitas — gunakan id_token.

2FA / MFA

Faktor kedua adalah peningkatan keamanan dengan rasio manfaat tertinggi. Urutan kekuatan:

  1. Kunci keamanan/passkey (WebAuthn/FIDO2) — terkuat, tahan phishing. Rekomendasi utama 2026.
  2. TOTP (aplikasi authenticator) — kode 6 digit berganti tiap 30 detik. Baik & murah.
  3. SMS OTP — lebih baik daripada tidak ada, tapi rentan SIM-swap. Hindari untuk akun bernilai tinggi.
node.js — totp
const { authenticator } = require('otplib');

// Saat aktivasi 2FA: buat secret per user, tampilkan QR
const secret = authenticator.generateSecret();
// simpan `secret` terenkripsi di DB milik user tsb

// Saat verifikasi kode dari pengguna
const valid = authenticator.verify({ token: userCode, secret });
// sediakan juga kode cadangan (backup codes) sekali-pakai

Siklus hidup sesi yang benar

Sesi bukan sekadar dibuat saat login lalu dilupakan. Ia punya siklus hidup yang harus Anda kelola secara sadar untuk mencegah pembajakan.

PeristiwaYang harus terjadi
Login berhasilTerbitkan ID sesi baru (regenerasi) untuk cegah session fixation.
Naik privileseRegenerasi sesi lagi saat pengguna elevasi (mis. masuk mode admin).
Idle timeoutAkhiri sesi setelah tak aktif (mis. 30 menit untuk aksi sensitif).
Absolute timeoutPaksa login ulang setelah durasi maksimum (mis. 8–24 jam) apa pun aktivitasnya.
LogoutHapus sesi di server & kosongkan cookie — jangan sekadar hapus di klien.
Ganti password / curigaCabut semua sesi aktif pengguna tersebut.
⚠ Session fixation

Jika Anda tidak mengganti ID sesi saat login, penyerang bisa "menanam" ID sesi ke korban lebih dulu, lalu memakainya setelah korban login. Selalu regenerasi ID sesi pada perubahan status autentikasi.

Magic link (passwordless)

Magic link mengirim tautan sekali-pakai ke email untuk login tanpa password. Bila diterapkan benar, ia menghapus risiko password lemah. Aturannya: token acak kuat, berumur sangat pendek (mis. 10 menit), sekali pakai (hapus setelah dipakai), terikat ke email yang diminta, dan dikirim via saluran aman. Ingat: keamanannya kini bergantung pada keamanan email pengguna.

✓ Ringkasan bab

Pilih session untuk kontrol ketat, JWT untuk skala/API (dengan access pendek + refresh yang bisa dicabut). Setel cookie HttpOnly; Secure; SameSite. Kunci algoritma JWT. Tawarkan 2FA (passkey/TOTP) dan pertimbangkan magic link. Selalu buat pesan kegagalan login generik dan batasi percobaan (lihat Bab 11).

Bab 07

Otorisasi: RBAC, ABAC & Multi-tenant

// sec-ops/07_authorization

Setelah tahu siapa pengguna, pertanyaan berikutnya: apa yang boleh ia lakukan? Otorisasi adalah tempat lahirnya kelas bug paling berbahaya dan paling sering terlewat — karena ia tidak "terlihat" seperti fitur, dan tesnya sering hanya menguji jalur bahagia. Satu cek izin yang hilang bisa membuka data seluruh pengguna.

⚠ Aturan mutlak

Otorisasi terjadi di server, pada setiap request, untuk setiap sumber daya. Menyembunyikan tombol di UI bukan keamanan — penyerang memanggil API langsung. Jangan pernah percaya userId atau role yang dikirim klien; ambil dari sesi/token yang terverifikasi di server.

Prinsip: default deny & least privilege

Rancang sistem agar default-nya menolak: akses hanya diberikan bila ada aturan eksplisit yang mengizinkan. Lawannya — default allow lalu menambal larangan — pasti bocor karena Anda akan lupa satu jalur. Padukan dengan least privilege: setiap peran mendapat hak seminimal yang diperlukan untuk tugasnya.

RBAC: Role-Based Access Control

Model paling umum: pengguna punya peran (admin, editor, viewer), dan peran punya izin. Sederhana, mudah dipahami, cukup untuk mayoritas aplikasi.

node.js — rbac
const PERMISSIONS = {
  admin:  ['user:read','user:write','billing:manage'],
  editor: ['post:read','post:write'],
  viewer: ['post:read'],
};

function can(user, perm) {
  return (PERMISSIONS[user.role] || []).includes(perm);
}

// Middleware: default DENY
const require_ = (perm) => (req, res, next) => {
  if (!req.user || !can(req.user, perm))
    return res.status(403).json({ error: 'forbidden' });
  next();
};

app.delete('/users/:id', require_('user:write'), handler);

ABAC: Attribute-Based Access Control

Ketika RBAC tak cukup ekspresif ("editor boleh mengedit hanya artikel miliknya, di jam kerja, dari kantor"), gunakan ABAC — keputusan berdasarkan atribut subjek, sumber daya, aksi, dan lingkungan. Lebih fleksibel, lebih kompleks. Sering diterapkan lewat mesin kebijakan (mis. OPA/Rego).

pseudo — abac policy
# Izinkan jika: pemilik sumber daya ATAU admin tenant
allow if resource.owner_id == subject.id
allow if subject.role == "admin" and resource.tenant_id == subject.tenant_id
# default: deny

IDOR: bug otorisasi paling umum

Insecure Direct Object Reference terjadi saat aplikasi memakai ID dari klien untuk mengambil objek tanpa mengecek kepemilikan. Contoh: GET /invoices/1043 mengembalikan faktur siapa pun asal tahu nomornya. Ini sepele ditemukan penyerang (cukup ganti angka) dan sering fatal.

node.js — cegah IDOR
// SALAH — ambil hanya berdasarkan id dari URL
const inv = await db.invoices.findById(req.params.id);

// BENAR — batasi ke pemilik / tenant dari sesi terverifikasi
const inv = await db.invoices.findOne({
  id: req.params.id,
  tenant_id: req.user.tenantId   // dari token, bukan dari klien
});
if (!inv) return res.status(404).end();  // jangan bocorkan keberadaan

Multi-tenant: isolasi adalah segalanya

Pada SaaS multi-tenant, kegagalan otorisasi berarti data satu pelanggan bocor ke pelanggan lain — mimpi buruk komersial. Strategi isolasi:

ModelIsolasiTrade-off
Database per tenantTerkuatMahal, sulit skala ke banyak tenant kecil
Schema per tenantKuatMenengah; batas jumlah schema
Kolom tenant_id bersamaBergantung disiplin kodeMurah & skalabel, tapi 1 query lupa filter = bocor
▲ Paksa filter tenant di lapisan data

Jika memakai kolom tenant_id bersama, jangan andalkan setiap developer ingat menambahkan filter. Terapkan di lapisan bawah: middleware yang menyuntikkan filter tenant otomatis, Row-Level Security (RLS) di PostgreSQL, atau scope global ORM. Buat "lupa memfilter" menjadi mustahil, bukan sekadar tidak dianjurkan.

sql — postgres rls
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON invoices
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

-- Set per koneksi/transaksi dari nilai sesi terverifikasi
SET app.tenant_id = '...';

Sistem yang benar-benar aman adalah yang dimatikan, dicor dalam beton, dan disegel di ruang berlapis timah dengan penjaga bersenjata — dan bahkan itu pun saya ragu.

Gene Spafford, ilmuwan komputer
✓ Ringkasan bab

Default deny, least privilege. Cek izin di server tiap request. RBAC untuk kasus umum, ABAC untuk aturan kompleks. Waspadai IDOR — selalu batasi query ke pemilik/tenant dari sesi terverifikasi. Untuk multi-tenant, tegakkan isolasi di lapisan data (RLS/scope global), bukan hanya di kode aplikasi.

Bab 08

Masking Data, PII & UU PDP

// sec-ops/08_pii_pdp

Data pribadi bukan sekadar aset teknis — ia adalah kepercayaan yang dititipkan, dan sejak berlakunya UU Perlindungan Data Pribadi (UU No. 27 Tahun 2022), ia juga adalah kewajiban hukum. Bab ini membahas cara mengenali, meminimalkan, menyamarkan, dan melindungi data pribadi agar aplikasi Anda patuh dan tepercaya.

◆ Bukan nasihat hukum

Bagian ini menjelaskan prinsip praktis UU PDP untuk pengembang. Untuk kepatuhan formal, konsultasikan dengan penasihat hukum. Fokus kita: apa yang harus Anda bangun ke dalam kode.

Apa itu PII?

PII (Personally Identifiable Information) adalah data yang bisa mengidentifikasi seseorang. UU PDP membedakan data pribadi umum dan spesifik (sensitif).

KategoriContohPerlakuan
UmumNama, email, no. HP, alamat, NIKLindungi, minimalkan, enkripsi bila sensitif
Spesifik/sensitifData kesehatan, biometrik, keuangan, agama, orientasi, anakPerlindungan & persetujuan lebih ketat

Prinsip inti UU PDP untuk developer

Argumen bahwa Anda tidak peduli privasi karena tidak punya yang disembunyikan, sama saja dengan berkata Anda tidak peduli kebebasan berbicara karena tidak punya yang ingin dikatakan.

Edward Snowden

Masking: menampilkan tanpa membuka

Masking menyamarkan sebagian data saat ditampilkan, sementara nilai penuh tetap tersimpan aman dan hanya diakses saat benar-benar perlu. Contoh: 0812****7890, a***@gmail.com. Terapkan di lapisan penyajian, dan pastikan API tidak diam-diam mengembalikan nilai penuh.

javascript — masking
const maskEmail = (e) => {
  const [u, d] = e.split('@');
  return u[0] + '***' + '@' + d;
};
const maskPhone = (p) => p.slice(0,4) + '****' + p.slice(-4);
const maskNIK   = (n) => '************' + n.slice(-4);

// Di response API, kembalikan versi ter-masking secara default
return { name: u.name, email: maskEmail(u.email), phone: maskPhone(u.phone) };

Anonimisasi vs pseudonimisasi

TeknikBisa dibalik?Contoh
PseudonimisasiYa, dengan kunci terpisahGanti nama dengan token; peta token disimpan aman
AnonimisasiTidak (idealnya)Agregasi, generalisasi, hapus pengenal; untuk analitik
▲ Anonimisasi itu sulit

Data yang "dianonimkan" sering bisa di-re-identifikasi dengan menggabungkan beberapa atribut (mis. kode pos + tanggal lahir + jenis kelamin). Anonimisasi sejati memerlukan teknik seperti k-anonymity atau differential privacy. Jangan menganggap sekadar menghapus nama sudah cukup.

Menghormati hak penghapusan

Ketika pengguna meminta penghapusan, Anda harus benar-benar menghapus/anonimkan — termasuk di backup (sesuai kebijakan retensi), log, dan sistem pihak ketiga. Rancang skema sejak awal agar penghapusan bisa dijalankan tanpa merusak integritas referensial (mis. anonimkan baris, jangan hard-delete yang memutus relasi keuangan yang wajib disimpan).

✓ Ringkasan bab

Kenali PII, kumpulkan seminimal mungkin, dapatkan persetujuan yang sah. Enkripsi data sensitif (Bab 3), masking di penyajian, dan pisahkan pengenal bila memungkinkan. Bangun mekanisme hak subjek data (akses, koreksi, hapus) sejak awal. Siapkan prosedur notifikasi kebocoran sesuai UU PDP — 3×24 jam adalah tenggat yang menegangkan bila Anda belum siap.

Bab 09

OWASP Top 10: Bedah & Mitigasi

// sec-ops/09_owasp_top10

OWASP Top 10 adalah daftar konsensus risiko keamanan aplikasi web paling kritis, disusun dari data industri. Jika Anda hanya punya waktu untuk memahami satu kerangka, jadikan ini. Bab ini membedah setiap kategori (edisi 2021, yang masih menjadi rujukan utama hingga 2026) beserta mitigasi konkret.

A01 — Broken Access Control

Risiko nomor satu. Pengguna bisa bertindak di luar izinnya: mengakses akun lain (IDOR), menaikkan privilese, atau memanggil endpoint admin. Mitigasi: default deny, cek otorisasi server-side tiap request, batasi query ke pemilik/tenant (lihat Bab 7). Uji dengan sengaja mencoba akses lintas-pengguna.

A02 — Cryptographic Failures

Data sensitif tak terlindungi: transmisi tanpa TLS, password ter-hash lemah, kunci hardcoded, algoritma usang. Mitigasi: TLS di mana-mana, enkripsi at-rest, Argon2/bcrypt untuk password, KMS untuk kunci (Bab 3 & 4). Jangan menyimpan data yang tak perlu disimpan.

A03 — Injection

Input tak tepercaya diinterpretasikan sebagai perintah: SQL injection, NoSQL injection, command injection, LDAP. Mitigasi: query parameterized/prepared statements, ORM, validasi allowlist, escaping sesuai konteks. Jangan pernah merangkai query dengan string concatenation (Bab 10).

A04 — Insecure Design

Cacat pada tingkat desain, bukan implementasi — mis. alur bisnis yang bisa disalahgunakan (kupon tak terbatas, reset password lemah). Mitigasi: threat modeling (Bab 2), pola desain aman, batasan bisnis eksplisit, dan pengujian penyalahgunaan (abuse cases), bukan hanya use cases.

A05 — Security Misconfiguration

Default tak aman, port terbuka, direktori terekspos, header keamanan hilang, pesan error verbose, cloud bucket publik. Mitigasi: hardening baseline, hapus fitur/akun default, tutup pesan error detail di produksi, pasang security headers, dan pindai konfigurasi secara otomatis.

http — security headers
Content-Security-Policy: default-src 'self'; object-src 'none'; frame-ancestors 'none'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=63072000; includeSubDomains
Permissions-Policy: geolocation=(), microphone=(), camera=()

A06 — Vulnerable & Outdated Components

Memakai pustaka/framework dengan celah yang diketahui. Mitigasi: inventaris dependency, pemindaian SCA otomatis, pin versi, patch rutin (Bab 13). Sebagian besar aplikasi punya lebih banyak kode pihak ketiga daripada kode sendiri.

A07 — Identification & Authentication Failures

Autentikasi lemah: brute-force tak dibatasi, password lemah diterima, sesi tak kedaluwarsa, kredensial dapat ditebak. Mitigasi: rate limit login, 2FA, kebijakan password modern, manajemen sesi benar (Bab 6 & 11).

A08 — Software & Data Integrity Failures

Memercayai kode/data tanpa verifikasi integritas: update tak ditandatangani, pipeline CI/CD yang dikompromi, deserialisasi tak aman. Mitigasi: tanda tangan & verifikasi artefak, kunci integritas dependency (lockfile + hash), amankan pipeline, hindari deserialisasi objek tak tepercaya.

A09 — Security Logging & Monitoring Failures

Tanpa logging & monitoring memadai, serangan tak terdeteksi berbulan-bulan. Mitigasi: catat peristiwa keamanan penting, pusatkan log, pasang alert anomali, dan latih respons (Bab 12 & 14).

A10 — Server-Side Request Forgery (SSRF)

Aplikasi mengambil URL yang ditentukan pengguna, memungkinkan penyerang menjangkau sistem internal (mis. metadata cloud 169.254.169.254). Mitigasi: allowlist domain tujuan, blokir alamat internal/loopback, validasi setelah resolusi DNS, dan jangan teruskan respons mentah (Bab 10).

A01 Broken Access Control A02 Cryptographic Failures A03 Injection A04 Insecure Design A05 Misconfiguration A06 Outdated Comp. A07 Auth Failures A08 Integrity Fail. A09 Logging Fail. A10 SSRF OWASP Top 10 (2021) — panjang bar ~ frekuensi relatif
Gambar 9.1 — Sepuluh kategori risiko OWASP dan urutannya.
✓ Ringkasan bab

OWASP Top 10 adalah peta prioritas, bukan daftar lengkap. Tiga teratas — access control, kripto, injection — menutup porsi besar risiko nyata. Jadikan daftar ini bagian dari review kode dan pengujian rutin. Bab-bab berikut memperdalam mitigasi injection, validasi, rate limit, logging, dan rantai pasok.

Bab 10

Validasi & Sanitasi Input: XSS, SQLi, CSRF, SSRF

// sec-ops/10_input_validation

Ada satu kalimat yang bila Anda tato di dinding tim akan mencegah setengah dari semua kerentanan: jangan pernah percaya input. Setiap byte yang datang dari luar sistem Anda — form, URL, header, cookie, file, API pihak ketiga — berpotensi jahat sampai terbukti sebaliknya. Bab ini mengubah paranoia sehat itu menjadi praktik konkret.

Validasi vs sanitasi vs escaping

IstilahKapanContoh
ValidasiSaat input masukTolak yang tak sesuai bentuk (email, panjang, tipe)
SanitasiMembersihkan inputBuang tag berbahaya dari HTML yang diizinkan
EscapingSaat outputUbah karakter khusus sesuai konteks tujuan
▲ Validasi allowlist, bukan denylist

Jangan mencoba menebak "semua yang jahat" untuk diblokir (denylist) — Anda selalu kalah cepat. Definisikan "apa yang valid" dan tolak sisanya (allowlist). Validasi bentuk (skema) di server; validasi klien hanya untuk UX, bukan keamanan.

node.js — schema validation
const { z } = require('zod');

const SignupSchema = z.object({
  email: z.string().email().max(254),
  age:   z.number().int().min(13).max(120),
  role:  z.enum(['viewer','editor']),  // allowlist — 'admin' ditolak
}).strict();                          // tolak field tak dikenal (anti mass-assign)

const parsed = SignupSchema.safeParse(req.body);
if (!parsed.success) return res.status(400).json({ error: 'invalid input' });

SQL Injection

Terjadi saat input pengguna dirangkai langsung ke query SQL. Penyerang menyisipkan sintaks SQL untuk membaca/mengubah/menghapus data. Solusi tunggal & final: query terparameter (prepared statements) atau ORM. Titik.

sql injection
// SALAH — string concatenation. Input: ' OR '1'='1
db.query(`SELECT * FROM users WHERE email = '` + email + `'`);

// BENAR — parameterized. Nilai tak pernah jadi "kode"
db.query('SELECT * FROM users WHERE email = $1', [email]);

// BENAR — ORM
await User.findOne({ where: { email } });

Cross-Site Scripting (XSS)

Penyerang menyisipkan skrip yang dijalankan di browser korban — mencuri sesi, mengubah halaman, keylogging. Tiga jenis: stored (tersimpan di DB), reflected (dipantulkan dari request), dan DOM-based (di sisi klien). Mitigasi: escaping saat output sesuai konteks (HTML, atribut, JS, URL), Content-Security-Policy, dan jangan pernah menaruh input mentah ke innerHTML.

javascript — xss
// SALAH — input mentah ke DOM
el.innerHTML = userInput;    // <img src=x onerror=alert(1)>

// BENAR — perlakukan sebagai teks, bukan HTML
el.textContent = userInput;

// Jika HTML kaya memang diperlukan, sanitasi dgn pustaka teruji
el.innerHTML = DOMPurify.sanitize(userHtml);

Framework modern (React, Vue, Svelte) meng-escape secara default — pertahankan itu. Waspadai jalan pintas berbahaya seperti dangerouslySetInnerHTML atau v-html.

Cross-Site Request Forgery (CSRF)

Situs jahat memicu request ke aplikasi Anda memakai sesi korban yang sedang login (mis. diam-diam mengirim form transfer). Mitigasi: token anti-CSRF per sesi/form, cookie SameSite, dan verifikasi header Origin/Referer untuk aksi state-changing. API berbasis token bearer (bukan cookie) umumnya kebal CSRF klasik.

node.js — csrf
// Sisipkan token ke form; verifikasi saat POST
app.post('/transfer', (req, res) => {
  if (req.body._csrf !== req.session.csrfToken)
    return res.status(403).end('CSRF token invalid');
  // ...proses...
});
// + cookie SameSite=Lax/Strict sebagai lapis kedua

Server-Side Request Forgery (SSRF)

Bila aplikasi mengambil URL yang diberi pengguna (webhook, preview link, import dari URL), penyerang bisa mengarahkannya ke sumber daya internal. Target favorit: endpoint metadata cloud yang menyimpan kredensial.

node.js — cegah ssrf
const dns = require('dns').promises;
const net = require('net');

async function safeFetchUrl(url) {
  const u = new URL(url);
  if (!['http:','https:'].includes(u.protocol)) throw new Error('protokol');
  const { address } = await dns.lookup(u.hostname);
  if (isPrivate(address)) throw new Error('alamat internal ditolak');
  return fetch(url, { redirect: 'error' });   // jangan ikuti redirect diam-diam
}
function isPrivate(ip){
  return /^(10\.|127\.|169\.254\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.)/.test(ip)
    || ip === '::1';
}
⚠ File upload & command injection

Upload file: validasi tipe (magic bytes, bukan hanya ekstensi), batasi ukuran, simpan di luar webroot, beri nama acak, jangan pernah eksekusi. Command injection: hindari memanggil shell dengan input pengguna; bila terpaksa, gunakan API yang memisahkan argumen (execFile) — jangan exec dengan string yang dirangkai.

✓ Ringkasan bab

Jangan percaya input. Validasi bentuk dengan skema allowlist di server. Cegah injeksi dengan query terparameter. Cegah XSS dengan escaping kontekstual + CSP. Cegah CSRF dengan token + SameSite. Cegah SSRF dengan allowlist tujuan + blokir alamat internal. Ini adalah bab dengan rasio "usaha kecil, dampak besar" tertinggi.

Bab 11

Rate Limiting & Anti-abuse

// sec-ops/11_rate_limit

Beberapa serangan tidak menembus dinding — mereka mengetuk pintu jutaan kali sampai satu terbuka, atau membanjiri Anda sampai tumbang. Rate limiting adalah pengatur lalu lintas yang menjaga aplikasi tetap adil dan hidup: membatasi berapa banyak yang boleh dilakukan seseorang dalam rentang waktu tertentu.

Apa yang dilindungi rate limiting

Algoritma rate limiting

AlgoritmaSifatCatatan
Fixed windowHitung per jendela waktu tetapSederhana; ada lonjakan di batas jendela
Sliding windowJendela geserLebih halus & adil
Token bucketEmber token terisi berkalaIzinkan burst terkendali; populer
Leaky bucketAntrean bocor konstanMenghaluskan laju keluar
node.js — rate limit login
const rateLimit = require('express-rate-limit');

// Ketat khusus login: 5 percobaan / 15 menit / IP
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  standardHeaders: true,
  message: { error: 'Terlalu banyak percobaan, coba lagi nanti.' },
  keyGenerator: (req) => req.ip + ':' + (req.body?.email || ''),
});
app.post('/login', loginLimiter, loginHandler);

// Limit global lebih longgar untuk seluruh API
app.use(rateLimit({ windowMs: 60*1000, max: 120 }));
▲ Kunci rate limit dengan bijak

Membatasi hanya per-IP mudah di-bypass (botnet, proxy) dan bisa menghukum banyak pengguna di balik satu NAT/kantor. Kombinasikan sinyal: IP, akun, perangkat, dan endpoint. Untuk login, batasi per-akun dan per-IP. Di belakang proxy/CDN, pastikan Anda membaca IP asli (X-Forwarded-For) dengan benar dan tepercaya.

Rate limiting terdistribusi

Jika aplikasi berjalan di banyak instance, hitungan di memori lokal tak cukup — pengguna bisa berpindah instance. Gunakan store bersama seperti Redis untuk menyimpan penghitung secara atomik. Pertimbangkan juga memasang rate limit di lapisan edge (CDN/WAF/API gateway) agar trafik jahat berhenti sebelum mencapai aplikasi.

Lapisan anti-abuse lain

Keamanan adalah tentang mengelola risiko — Anda tidak bisa menghilangkannya, hanya bisa menurunkannya ke tingkat yang dapat diterima.

Bruce Schneier
✓ Ringkasan bab

Batasi endpoint sensitif & mahal secara ketat, seluruh API secara longgar. Kombinasikan kunci (IP + akun). Pakai store terdistribusi (Redis) untuk multi-instance dan dorong penyaringan ke edge. Tambahkan backoff, CAPTCHA adaptif, dan deteksi anomali sebagai lapisan. Selalu kembalikan pesan & status yang jelas (429) tanpa membocorkan detail internal.

Bab 12

Logging Aman & Audit Trail

// sec-ops/12_logging_audit

Ketika terjadi insiden, satu-satunya cara mengetahui apa yang terjadi adalah dengan melihat jejak. Log yang baik adalah kotak hitam aplikasi Anda: ia menjawab siapa melakukan apa, kapan, dari mana, dan dengan hasil apa. Tetapi log juga bisa menjadi sumber kebocoran jika salah kelola — karena ia sering menampung persis data yang harus dirahasiakan.

Dua jenis log yang berbeda tujuan

JenisUntukIsi
Log operasionalDebug & kesehatan sistemError, latensi, kejadian teknis
Audit trailAkuntabilitas & forensikAksi bisnis penting: siapa, apa, kapan, hasil

Apa yang WAJIB dicatat

⚠ Apa yang TIDAK boleh masuk log

Jangan pernah mencatat: password (mentah/hash), token/sesi, kunci & secret, nomor kartu penuh, OTP, atau PII sensitif tanpa masking. Log sering berakhir di sistem pihak ketiga, dashboard yang diakses banyak orang, dan retensi panjang — jadikan ia zona bebas-rahasia.

node.js — structured logging
const pino = require('pino');

// Redaksi otomatis field sensitif
const log = pino({
  redact: {
    paths: ['password','*.password','authorization','token','*.card','otp'],
    censor: '[REDACTED]'
  }
});

// Audit event terstruktur (bukan string bebas)
log.info({
  event: 'auth.login.success',
  actor: user.id,
  ip: req.ip,
  ua: req.headers['user-agent'],
  ts: new Date().toISOString()
}, 'user login');

Sifat audit trail yang baik

Monitoring & alerting

Log yang tak pernah dilihat sama tak bergunanya dengan tidak ada log. Pasang alert untuk pola berbahaya: lonjakan kegagalan login, banyak 403, ekspor data tak biasa, error rate melonjak, atau akses di jam & lokasi ganjil. Tujuannya menyingkat dwell time — waktu penyerang bersembunyi tak terdeteksi — dari bulanan menjadi menit.

◆ Retensi & kepatuhan

Seimbangkan dua tekanan: audit trail harus disimpan cukup lama untuk forensik & kepatuhan, tetapi PII di log tunduk pada minimalisasi & hak penghapusan (Bab 8). Solusi umum: pisahkan audit trail (identitas + aksi, retensi panjang) dari log yang memuat konten (retensi pendek, di-masking).

✓ Ringkasan bab

Catat peristiwa keamanan & aksi bisnis penting secara terstruktur. Redaksi rahasia & PII sebelum menulis. Buat audit trail immutable, tersinkron waktu, terkorelasi, dan terpusat. Pasang alert agar deteksi terjadi dalam menit, bukan bulan. Log yang baik adalah perbedaan antara "kami tahu persis apa yang terjadi" dan "kami tidak tahu".

Bab 13

Keamanan Rantai Pasok & Dependency

// sec-ops/13_supply_chain

Aplikasi modern adalah kolase. Anda mungkin menulis 10% kode; 90% sisanya datang dari ratusan pustaka pihak ketiga, yang masing-masing membawa dependensinya sendiri. Setiap paket itu adalah pintu yang Anda percayai tanpa pernah membacanya. Keamanan rantai pasok adalah tentang mempercayai dengan verifikasi.

Anda tidak bisa mempercayai kode yang tidak sepenuhnya Anda buat sendiri.

Ken Thompson, "Reflections on Trusting Trust" (kuliah Turing Award, 1984)

Vektor serangan rantai pasok

SeranganCara kerja
Kerentanan diketahui (CVE)Pakai versi pustaka dengan celah yang sudah dipublikasikan
Paket jahatPustaka yang sengaja berisi malware/backdoor
TyposquattingNama paket mirip yang populer (mis. expres vs express)
Dependency confusionPaket publik menyamar sebagai paket internal Anda
Akun maintainer dibajakVersi baru yang jahat dirilis dari akun sah
Build/CI dikompromiArtefak disuntik saat proses build

Pertahanan berlapis

1. Kunci versi (lockfile)

Selalu commit lockfile (package-lock.json, yarn.lock, poetry.lock). Ia mengunci versi persis beserta hash integritas, sehingga build reprodusibel dan paket tak diam-diam berganti. Di CI gunakan npm ci (bukan npm install) agar patuh pada lockfile.

2. Pindai kerentanan (SCA)

bash — sca
# Audit dependency untuk CVE diketahui
npm audit --audit-level=high

# Atau alat khusus (contoh)
osv-scanner --lockfile=package-lock.json
trivy fs --scanners vuln .

# Jadikan bagian CI — gagalkan build jika ada CVE kritis

3. Otomasi update

Pasang bot pembaruan dependency (Dependabot/Renovate) yang membuka PR otomatis untuk patch keamanan. Kombinasikan dengan tes otomatis agar update aman digabung cepat. Jangan menunda patch keamanan — jendela antara publikasi CVE dan eksploitasi massal makin sempit.

4. SBOM & provenance

Hasilkan SBOM (Software Bill of Materials) — daftar lengkap komponen aplikasi Anda. Saat CVE baru muncul, SBOM memungkinkan Anda menjawab "apakah kami terdampak?" dalam menit. Untuk tingkat lanjut, verifikasi provenance artefak (mis. SLSA, penandatanganan Sigstore) agar yakin build berasal dari sumber yang sah.

5. Higienis memilih dependency

▲ Amankan pipeline CI/CD

Pipeline Anda memegang kunci ke produksi. Batasi izin token CI (least privilege), pin versi action/plugin ke commit hash, jangan jalankan kode PR tak tepercaya dengan secret produksi, dan audit siapa yang bisa mengubah workflow. CI yang dibobol = seluruh rilis dibobol.

✓ Ringkasan bab

Commit lockfile, pindai CVE di CI, otomatiskan patch, hasilkan SBOM, dan pilih dependency dengan higienis. Amankan pipeline CI/CD seketat produksi. Rantai pasok adalah permukaan serangan yang tak terlihat namun luas — perlakukan kode pihak ketiga dengan skeptisisme yang sehat, bukan kepercayaan buta.

Bab 14

Incident Response: Saat Alarm Berbunyi

// sec-ops/14_incident_response

Bukan soal jika, melainkan kapan. Cepat atau lambat, sesuatu akan terjadi: kredensial bocor, celah dieksploitasi, atau data raib. Yang membedakan perusahaan yang pulih dari yang hancur bukanlah ketiadaan insiden, melainkan kesiapan meresponsnya. Rencana yang ditulis saat tenang jauh lebih baik daripada improvisasi saat panik pukul tiga pagi.

Enam fase incident response (NIST)

FaseTujuan
1. PersiapanRencana tertulis, peran & kontak, alat, latihan sebelum insiden
2. IdentifikasiDeteksi & konfirmasi: benarkah ini insiden? Seberapa parah?
3. ContainmentBatasi penyebaran: isolasi sistem, cabut kredensial, hentikan pendarahan
4. EradicationHilangkan akar: tutup celah, hapus akses & malware penyerang
5. RecoveryPulihkan layanan dengan aman, pantau kekambuhan
6. Lessons LearnedPost-mortem tanpa menyalahkan; perbaiki agar tak terulang
Prepare Identify Contain Eradicate Recover Learn
Gambar 14.1 — Siklus respons insiden. "Learn" mengumpan balik ke "Prepare".

Siapkan sebelum, bukan saat

▲ Jaga bukti forensik

Saat containment, jangan buru-buru mematikan/menghapus segalanya — Anda bisa menghancurkan bukti yang dibutuhkan untuk memahami serangan & kewajiban pelaporan. Ambil snapshot, simpan log, catat linimasa. Isolasi (putus jaringan) sering lebih baik daripada menghapus.

Kewajiban notifikasi

Bila insiden melibatkan data pribadi, UU PDP mewajibkan notifikasi ke otoritas dan subjek data dalam tenggat (umumnya 3×24 jam). Siapkan template komunikasi sebelumnya: jujur, jelas, tanpa membocorkan detail yang bisa dimanfaatkan penyerang lain. Transparansi yang cepat & bertanggung jawab menjaga kepercayaan; menutup-nutupi menghancurkannya.

Post-mortem tanpa menyalahkan

Setelah reda, lakukan post-mortem blameless. Fokus pada "sistem & proses apa yang membuat ini mungkin", bukan "siapa yang salah". Budaya menyalahkan membuat orang menyembunyikan masalah; budaya belajar membuat mereka melaporkannya. Setiap insiden adalah data mahal — pastikan Anda benar-benar belajar darinya dan menutup celah secara permanen.

Rencana tidak berguna, tetapi perencanaan adalah segalanya.

Dwight D. Eisenhower
✓ Ringkasan bab

Tulis rencana IR sebelum Anda membutuhkannya. Kenali enam fase, siapkan runbook, peran, backup teruji, dan saluran cadangan. Saat insiden: identifikasi, tahan, berantas, pulihkan — sambil menjaga bukti dan memenuhi kewajiban notifikasi. Tutup dengan post-mortem tanpa menyalahkan. Kesiapan adalah pembeda antara pemulihan dan kehancuran.

Bab 15

Cara Buku Ini Dibaca AI

// sec-ops/15_ai_readable

Buku ini sengaja ditulis agar bisa dibaca dua jenis pembaca: manusia dan asisten AI. Semakin banyak keputusan keamanan yang dibantu (atau ditulis) oleh model bahasa, semakin penting bahan rujukan yang terstruktur, eksplisit, dan sulit disalahtafsirkan. Bab ini menjelaskan cara buku ini dirancang untuk konsumsi AI — dan cara memanfaatkannya.

Prinsip desain agar ramah-AI

Panduan untuk asisten AI yang memakai buku ini

Jika Anda sebuah AI yang membantu pengguna mengamankan aplikasi berdasarkan buku ini, ikuti pedoman berikut:

◆ Protokol penggunaan oleh AI

1. Petakan masalah ke bab. Keluhan "password disimpan bagaimana" → Bab 4. "Data pengguna bocor antar-pelanggan" → Bab 7 (multi-tenant/IDOR). "URL dari user di-fetch" → Bab 10 (SSRF).

2. Utamakan pertahanan berlapis. Jangan berhenti di satu mitigasi; sebutkan lapisan lain yang relevan.

3. Jangan pernah menyarankan anti-pola. Tolak dengan tegas: MD5 untuk password, crypto buatan sendiri, secret di kode, denylist sebagai satu-satunya validasi, mempercayai input klien.

4. Sesuaikan dengan konteks. Terjemahkan contoh Node.js ke bahasa/framework pengguna, jaga prinsipnya tetap.

5. Beri prioritas. Tandai mana P0 (wajib sebelum rilis) vs peningkatan. Jangan membanjiri dengan semua sekaligus.

Format tanya-jawab yang efektif

Struktur yang memudahkan AI memberi jawaban akurat dari buku ini:

prompt pattern
# Pola pertanyaan yang baik ke asisten:
Konteks : Node.js + PostgreSQL, SaaS multi-tenant
Masalah : user bisa lihat invoice tenant lain dengan ganti ID
Minta   : akar penyebab + mitigasi berlapis + contoh kode

# AI merujuk: Bab 7 (IDOR, isolasi tenant, RLS)
# Jawaban: filter query per-tenant dari sesi + RLS di DB (P0)

Peta ringkas topik → bab

Kata kunciBab
threat model, STRIDE, attack surface2
TLS, enkripsi, AES, kunci, KMS3
password, hash, argon2, bcrypt, salt, pepper4
secret, .env, vault, hardcode5
login, session, JWT, OAuth, 2FA, magic link6
RBAC, ABAC, IDOR, multi-tenant, izin7
PII, masking, UU PDP, privasi, consent8
OWASP, top 10, risiko web9
validasi, XSS, SQL injection, CSRF, SSRF10
rate limit, brute force, anti-abuse11
log, audit trail, monitoring12
dependency, CVE, SBOM, rantai pasok13
insiden, breach, response, backup14
✓ Ringkasan bab

Struktur buku ini — heading berurutan, anchor stabil, langkah eksplisit, penanda semantik, kode beranotasi — dirancang agar manusia dan AI sama-sama bisa menavigasinya dengan andal. Ketika AI memakai buku ini, ia harus memetakan masalah ke bab, mengutamakan pertahanan berlapis, menolak anti-pola, dan memberi prioritas yang jelas.

Bab 16

Penutup, FAQ, Glosarium & Checklist

// sec-ops/16_closing

Kita telah menempuh perjalanan panjang: dari cara berpikir seperti penyerang, menyusuri kripto dan kredensial, membangun identitas dan akses, memperkuat aplikasi, sampai bersiap menghadapi hari terburuk. Bila ada satu pesan yang saya ingin Anda bawa pulang, ini dia.

Keamanan bukanlah tujuan yang pernah "selesai". Ia adalah disiplin berkelanjutan — kebiasaan yang Anda anyam ke dalam cara tim Anda merancang, menulis, meninjau, dan mengoperasikan perangkat lunak. Anda tidak perlu menjadi ahli kriptografi untuk membangun aplikasi yang aman. Anda perlu konsisten menerapkan hal-hal mendasar yang benar: hashing yang tepat, validasi input, otorisasi server-side, secret yang tak bocor, dan kesiapan merespons.

Keamanan bukanlah sesuatu yang Anda beli, melainkan sesuatu yang Anda lakukan — dan butuh keahlian, bukan sekadar anggaran.

Kevin Mitnick, konsultan keamanan

Aplikasi yang aman adalah aplikasi yang layak dijual, layak dipercaya, dan layak Anda banggakan. Mulailah dari mana pun Anda berada sekarang — jalankan Audit Keamanan, pilih tiga hal berskor terendah, dan perbaiki minggu ini. Lakukan itu berulang, dan dalam beberapa bulan aplikasi Anda akan berubah dari "jalan" menjadi "tahan serangan".

FAQ — Pertanyaan yang Sering Diajukan

1. Aplikasi saya kecil, apakah tetap perlu semua ini?

Ya, secara proporsional. Penyerang otomatis tidak peduli ukuran Anda — mereka memindai internet secara acak. Fondasi (hashing benar, TLS, validasi input, no-hardcoded-secret) wajib bahkan untuk proyek terkecil. Kontrol lanjutan bisa dinaikkan seiring pertumbuhan.

2. Dari mana saya harus mulai jika waktu terbatas?

Urutan prioritas: (1) hashing password benar, (2) TLS di mana-mana, (3) validasi input + query terparameter, (4) otorisasi server-side, (5) tidak ada secret di kode. Kelima ini menutup mayoritas risiko nyata.

3. Apakah HTTPS saja sudah cukup?

Tidak. HTTPS melindungi data in-transit, tapi tidak melindungi dari SQL injection, password lemah, atau otorisasi yang bocor. Ia satu lapisan penting, bukan solusi lengkap.

4. Perlukah saya mengenkripsi semua kolom database?

Tidak. Enkripsi kolom untuk data sangat sensitif (NIK, data kesehatan, nomor rekening) yang disimpan & ditampilkan utuh. Kolom yang perlu di-query jangan dienkripsi tanpa strategi khusus. Enkripsi seluruh volume/disk melindungi dari pencurian fisik.

5. JWT atau session, mana yang lebih baik?

Tergantung. Session untuk kontrol ketat & kemudahan revoke (web app). JWT untuk skala & API stateless (pakai access pendek + refresh yang bisa dicabut). Keduanya aman bila diterapkan benar.

6. Bagaimana kalau saya sudah terlanjur pakai MD5 untuk password?

Migrasikan dengan strategi rehash saat login (Bab 4). Untuk yang belum login, bungkus hash lama di dalam Argon2. Jangan biarkan MD5 tetap berjalan — itu berisiko tinggi.

7. Apakah saya perlu WAF (Web Application Firewall)?

WAF berguna sebagai lapisan tambahan (menyaring serangan umum, membantu rate limit & bot mitigation). Tapi ia bukan pengganti kode yang aman — anggap sebagai jaring pengaman, bukan pertahanan utama.

8. Berapa sering harus rotasi secret & kunci?

Terjadwal (mis. tiap 90 hari untuk kredensial, lebih jarang untuk kunci enkripsi dengan versioning) dan segera setelah ada indikasi kebocoran atau anggota tim keluar.

9. Bagaimana menyeimbangkan keamanan dengan UX?

Keamanan yang menyiksa pengguna akan dilanggar. Gunakan pendekatan adaptif: gesekan tinggi hanya untuk aksi/risiko tinggi (CAPTCHA saat mencurigakan, 2FA untuk transaksi besar), mulus untuk sisanya. Password manager, passkey, dan magic link sering menaikkan keamanan dan UX sekaligus.

10. Apakah open source lebih aman atau kurang aman?

Bukan otomatis keduanya. Open source memungkinkan audit publik, tapi hanya aman bila benar-benar diaudit & dipelihara. Yang penting: pemeliharaan aktif, respons cepat terhadap celah, dan komunitas yang peduli.

11. Bagaimana cara aman menangani upload file?

Validasi tipe via magic bytes (bukan ekstensi), batasi ukuran, simpan di luar webroot dengan nama acak, jangan pernah eksekusi, pindai malware bila relevan, dan sajikan lewat endpoint terkontrol dengan header yang benar (Bab 10).

12. Apakah menyimpan data di cloud otomatis aman?

Cloud menyediakan alat keamanan hebat, tapi tanggung jawab dibagi (shared responsibility). Provider mengamankan infrastruktur; Anda mengamankan konfigurasi, akses, dan aplikasi. Bucket publik yang salah konfigurasi adalah penyebab kebocoran yang sangat umum.

13. Bagaimana kalau tim saya tidak punya ahli keamanan?

Mulai dengan buku ini, checklist, dan alat otomatis (SCA, secret scanner, linter keamanan). Jadikan keamanan bagian dari review kode. Untuk audit mendalam sebelum rilis besar atau kepatuhan, pertimbangkan pentest pihak ketiga.

14. Seberapa penting penetration testing?

Sangat berharga untuk menemukan celah yang lolos dari review internal, terutama sebelum rilis besar atau saat menargetkan pelanggan enterprise. Lakukan berkala & setelah perubahan arsitektur signifikan.

15. Apa kesalahan keamanan paling umum yang Anda lihat?

Tiga besar: (1) otorisasi yang tidak dicek di server (IDOR), (2) secret ter-commit ke Git, dan (3) input yang dipercaya mentah-mentah. Ketiganya sederhana dicegah namun sering terlewat karena tekanan tenggat.

16. Apakah AI bisa menulis kode yang aman untuk saya?

AI bisa sangat membantu, tapi ia bisa juga mereproduksi anti-pola. Perlakukan kode buatan AI seperti kode dari kontributor baru: tinjau, uji, dan periksa terhadap prinsip di buku ini. Gunakan Bab 15 sebagai panduan agar AI memakai rujukan yang benar.

Glosarium

IstilahArti singkat
ABACKontrol akses berbasis atribut (subjek, sumber daya, aksi, lingkungan).
AEADEnkripsi terautentikasi — menjaga kerahasiaan & integritas sekaligus (mis. AES-GCM).
Argon2Fungsi hashing password modern, tahan GPU; varian argon2id direkomendasikan.
Audit trailCatatan tak-terubah tentang siapa melakukan apa dan kapan.
bcryptFungsi hashing password matang berbasis biaya (cost factor).
CIAConfidentiality, Integrity, Availability — tiga sifat data yang dijaga.
CSPContent-Security-Policy; header pembatas sumber untuk menahan XSS.
CSRFMemicu aksi memakai sesi korban dari situs jahat.
CVEIdentitas publik untuk kerentanan yang diketahui.
Defense in depthPertahanan berlapis; jangan bergantung pada satu kontrol.
HSTSHeader yang memaksa browser hanya memakai HTTPS.
IDORAkses objek orang lain karena tak ada cek kepemilikan.
JWTToken bertanda-tangan berisi klaim; autentikasi stateless.
KMS/HSMLayanan/perangkat pengelola kunci kriptografi.
Least privilegeBeri hak seminimal yang diperlukan.
MFA/2FAAutentikasi multi/dua faktor.
PepperRahasia tambahan untuk hashing, disimpan terpisah dari database.
PIIInformasi yang dapat mengidentifikasi individu.
RBACKontrol akses berbasis peran.
RLSRow-Level Security; pembatasan baris di level database.
SaltNilai acak unik per password untuk melumpuhkan rainbow table.
SBOMDaftar komponen perangkat lunak (bill of materials).
SSRFMemaksa server mengambil URL ke sasaran internal.
STRIDETaksonomi enam jenis ancaman dari Microsoft.
TLSProtokol enkripsi lalu lintas jaringan (dulu SSL).
XSSMenyisipkan skrip yang berjalan di browser korban.

Checklist Keamanan Produksi

Daftar periksa sebelum & sesudah rilis. [P0] wajib, [P1] penting, [P2] peningkatan.

Autentikasi & Sesi

Otorisasi & Data

Transport & Kripto

Input & Aplikasi

Secrets & Konfigurasi

Operasi, Rantai Pasok & IR

Tentang Penulis

Galih Prasetyo

Praktisi rekayasa perangkat lunak dengan minat pada keamanan aplikasi dan perlindungan data. Buku ini adalah usaha menuliskan hal-hal yang seharusnya diketahui setiap pembangun aplikasi sebelum menjual produknya — bukan sebagai teori akademis, melainkan sebagai praktik yang bisa langsung diterapkan.

Judul
Keamanan Aplikasi & Data — Bikin App yang Aman, Siap Dijual & Tahan Serangan
Penulis
Galih Prasetyo
Edisi
Pertama, 2026
Bahasa
Indonesia
Pembaca
Semua level — dan dapat dibaca AI
Cakupan
16 bab + alat audit interaktif

Untuk melangkah lebih jauh

Buku ini adalah fondasi, bukan garis akhir. Rujukan berikut memperdalam setiap tema dan diperbarui secara berkala oleh komunitas:

◆ Satu kebiasaan terakhir

Jadwalkan tinjauan keamanan rutin — bulanan atau per rilis besar. Jalankan ulang Audit Keamanan, perbarui dependency, tinjau log & akses, dan latih satu skenario incident response. Keamanan yang dirawat sedikit demi sedikit jauh mengungguli upaya heroik sesekali.


— Selesai — Bangun sesuatu yang layak dipercaya. —

▲ Ke Atas