Lo Kena Hack Bukan Karena Teknologi, Tapi Karena Asumsi

Sistem yang 3 tahun "aman" bukan karena jago, tapi karena belum diserang. 30 menit masuk ke startup dengan 2FA + WAF + encryption. Bukan teknologi yang lemah - asumsi yang salah. IP whitelist, frontend validation, dependency, log, 2FA.

· · 10 min read

Gue baru sadar kenapa sistem yang gue bangun selama 3 tahun "aman": bukan karena gue jago, tapi karena belum ada yang nyerang. Saat gue audit sistem startup lain yang punya 2FA, WAF, encryption at rest, dan pentest tahunan - 30 menit gue masuk. Bukan teknologi mereka yang lemah. Asumsi mereka yang salah.

Itu momen gue sadar security itu gak soal tool. Bukan soal bcrypt, bukan soal JWT, bukan soal OWASP checklist. Security itu soal asumsi mana yang lo pegang, dan mana yang bikin lo rapuh. Artikel ini bukan tentang "X aturan security." Ini tentang asumsi-asumsi yang diam-diam bikin sistem lo gampang dibobol, walau lo udah implementasi "best practice."

---

Asumsi #1: "Cuma Gue yang Tau Endpoint Ini"

Gue pernah nemu API endpoint internal yang exposed ke internet: /api/internal/sync-db. Auth-nya? IP whitelist. Tim dev pikir "cuma kantor yang bisa akses." Mereka lupa: VPN kantor dibagi ke freelancer, VPN config pernah leak di GitHub repo public, dan salah satu freelancer resign tapi VPN-nya gak di-revoke.

Gue ngetest dari VPS Singapore, pake IP yang gak di-whitelist. Blocked. Pake IP Indonesia yang ke-redirect via VPN kantor yang masih aktif? Masuk. 30 menit.

Code-nya aman. Auth-nya ada. Yang salah: asumsi "IP whitelist itu solid." IP whitelist cuma sekuat cara distribusi IP-nya. Kalau VPN leak, whitelist = ilusi.

Filosofi yang gue pelajarin: lo gak bisa secure apa yang lo gak tau inventory-nya. Sebelum nanya "aman gak endpoint ini," nanya dulu: "siapa aja yang bisa nyampe endpoint ini, dan jalur mana yang mereka lewat?" Inventory dulu, baru secure. Asumsi "cuma gue yang tau" itu paling berbahaya karena lo gak nge-list siapa yang sebenernya bisa nyampe.

---

Asumsi #2: "Input dari Client Lo Validasi Sekali Cukup"

Banyak dev nge-validasi input di frontend. Lalu di backend, langsung dipake. "Ah, frontend udah validasi, gak usah ulang."

Itu asumsi yang bikin sistem lo gampang di-bypass. Frontend itu convenience, bukan security. Browser gak harus jalanin JavaScript lo. curl bisa kirim body apa aja. Postman bisa edit request sebelum nyampe backend. Burp Suite bisa intercept dan modify.

Contoh konkret yang gue temui di audit: form register, frontend validasi email pake regex, password min 8 karakter. Backend langsung INSERT INTO users (email, password) VALUES (...). Gue bypass frontend, kirim password: "a" (1 karakter), backend nerima. Hash bcrypt-nya jalan, user ke-create dengan password 1 karakter. Selanjutnya, gue brute force login: 1 karakter = 62 percobaan doang (alphanumeric). Bisa berapa akun gue ambil alih?

Asumsi yang salah: "frontend = security layer." Frontend gak pernah security layer. Frontend itu UX layer. Security layer harus ada di backend, di database, di setiap boundary yang data lo lewatin.

Kayak yang gue baca dari artikel backend sebelumnya: defense in depth. Bukan "tambahin layer buat banyak layer." Tapi: tiap layer punya tanggung jawab sendiri, dan gak percaya layer sebelumnya. Client gak dipercaya. API gateway gak dipercaya. Bahkan service internal gak dipercaya service lain.

// Frontend - UX doang, gak security
if (!email.includes('@')) return alert('email invalid')

// Backend - ini yang security
if (!isValidEmail(email)) return res.status(400).json({ error: 'invalid email' })
if (password.length < 8) return res.status(400).json({ error: 'password too short' })

Frontend bisa di-bypass dalam 5 detik. Backend gak. Itu bedanya.

---

Asumsi #3: "Library yang Populer Itu Aman"

Gue pernah pake lodash di project. Versi 4.17.4. Populer, kan? Jutaan download per minggu. Pasti aman.

Tiga bulan kemudian, CVE keluar: prototype pollution. Attacker bisa inject property ke Object.prototype lewat _.merge atau _.set. Effect-nya? XSS, RCE, tergantung gimana lo pake lodash.

Yang bikin gue ngerasa bodoh: gue gak pernah audit dependency gue. Gue asumsi "npm install = safe." Padahal npm ecosystem itu wild west. 2024 ada 13.000+ package malicious yang di-pull-down setelah npm audit. Ada package yang di-hijack (account maintainer diambil alih), di-inject malicious code, 2 jam kemudian ke-download jutaan kali sebelum ketahuan.

Asumsi yang salah: "populer = audited." Populer cuma berarti banyak yang pake, bukan banyak yang audit. left-pad incident 2016 - satu package 11 baris code, break ribuan project karena dependency tree-nya nge-blok. event-stream 2018 - maintainer handover ke orang gak dikenal, orang itu inject crypto wallet stealer.

Yang gue lakuin sekarang:

Audit dependency tiap minggu
npm audit

Lock versi exact, bukan caret
"dependencies": {
"lodash": "4.17.21" // bukan ^4.17.21
}

Pake Renovate atau Dependabot buat auto-PR security update
Review package baru sebelum install - siapa maintainer-nya? commit history? download count?

Filosofi yang gue pelajarin: dependency itu asumsi yang lo outsource. Lo asumsi maintainer-nya jujur, code-nya audited, update-nya safe. Asumsi itu valid sampai gak valid. Lo tetep musti punya process buat detect kalo asumsi lo salah.

---

Asumsi #4: "Log Gak Ngandung Data Sensitif"

Ini asumsi yang bikin impact breach jadi 10x lebih parah. Lo encrypt database at rest. Lo encrypt connection TLS. Lo hash password pake bcrypt. Mantap.

Tapi log lo?

Gue pernah liat production log startup fintech. Tiap request di-log full body. Termasuk request /login yang body-nya:

{ "email": "user@startup.com", "password": "PlainTextPassword123" }

Password plain text di log. Database encrypt, password di-hash bcrypt. Tapi log? Plain text. Attacker yang dapet akses ke log aggregation system (Datadog, CloudWatch, ELK) = dapet semua credential user.

Asumsi yang salah: "log itu gak sensitif, gue bebas nulis apa aja buat debugging." Log itu data leak vector yang paling sering di-underrate. Gue pernah nemu:
• JWT token di log (bisa di-replay)
• Credit card number di log (PCI compliance violation)
• Session ID di log (bisa session hijack)
• API key third-party di log (bisa di-steal)

Rule yang gue pegang sekarang: log itu assume akan di-baca sama attacker. Jangan nulis apa pun yang lo gak mau attacker baca.

// Salah - password, token, PII masuk log
req.log.info({ body: req.body }, 'incoming request')

// Bener - redact sensitive fields sebelum log
const safeBody = redact(req.body, ['password', 'token', 'creditCard'])
req.log.info({ body: safeBody }, 'incoming request')

// Atau pake library kayak pino dengan redaction built-in
const logger = pino({
redact: ['req.body.password', 'req.headers.authorization', '*.creditCard']
})

Filosofi: lo gak bisa control siapa yang bakal baca log lo 6 bulan dari sekarang. DevOps baru, vendor, attacker yang breach log system. Yang lo bisa control: apa yang lo tulis ke log. Assume log = public document.

---

Asumsi #5: "2FA Itu Silver Bullet"

Banyak startup bangga "kami ada 2FA." Terus mereka berhenti mikir security. 2FA = selesai.

Salah. 2FA gak nyelamatin lo dari:

• Phishing yang simulate login page - user masukin password + 2FA code ke fake page, attacker relay ke real site, session di-curian real-time. Ini namanya reverse proxy phishing, kit kayak Evilginx. 2FA SMS atau TOTP gak nahan ini.

• Session hijacking - 2FA cuma validasi saat login. Setelah login, session cookie atau JWT di-issue. Attacker yang dapet session cookie (XSS, log leak, MITM) gak perlu 2FA. Dia udah authenticated.

• Sim swap attack - 2FA SMS? Attacker social engineer telecom buat pindah nomor ke SIM baru. 2FA code masuk ke SIM attacker. Account taken over.

• Stored credential - browser nyimpen password + device "trusted" setelah 2FA pertama. Attacker yang dapet akses device = akses tanpa 2FA.

Asumsi yang salah: "2FA = sistem aman." 2FA = 1 layer. Layer yang bisa di-bypass pake social engineering (phishing), session theft, atau device compromise. 2FA ngurangin risk, bukan nge-eliminasi.

Yang bener: 2FA + session management yang ketat (short-lived token, refresh rotation) + device fingerprinting + anomaly detection (login dari IP baru, geolocation mismatch) + phishing-resistant 2FA (WebAuthn / passkey, yang gak bisa di-phish karena domain-bound).

Filosofi yang gue pelajarin: gak ada single control yang cukup. Security itu layers yang masing-masing nge-address attack vector beda. 2FA nge-address password theft. Tapi gak nge-address session theft. Session management nge-address session theft, tapi gak nge-address device compromise. Tiap layer ada gap. Lo tumpuk layer bukan buat "tambah aman," tapi buat nutup gap layer lain.

---

Asumsi yang Paling Berbahaya: "Gue Bukan Target"

Gue pernah omong sama founder startup kecil: "kami kecil, gak ada yang bakal nyerang." 6 bulan kemudian, server mereka jadi crypto mining botnet. Mereka bukan target. Mereka target of opportunity.

Attacker gak scan target spesifik. Mereka scan internet - Shodan, Censys, masscan - nyari vulnerability massal. "Siapa aja yang expose Elasticsearch tanpa auth?" Dapet 10.000 server. Semua di-compromise otomatis. Lo gak perlu penting. Lo cuma perlu vulnerable.

Asumsi "gue bukan target" = asumsi "gue gak akan kena hujan karena gue lagi di rumah." Padahal atap lo bocor. Attacker automated gak peduli lo siapa. Mereka peduli lo bisa di-compromise atau gak.

Filosofi yang gue pelajarin: di internet, lo selalu di-scan. Tiap detik. Automated bot nyari open port, default credential, vulnerable software. Lo gak perlu menjadi "target" buat kena. Lo cuma perlu menjadi "bisa di-bobol."

---

Yang Gue Pelajarin dari Sisi Mindset

Security itu gak soal teknologi. Teknologi itu implementasi. Security itu soal asumsi mana yang lo pegang, dan mana yang bisa di-falsify.

Tiap design decision lo bikin, tanya diri lo sendiri: "asumsi apa yang bikin ini aman?" Lalu tanya: "apa yang terjadi kalau asumsi itu salah?"

• "IP whitelist aman" → asumsi: VPN gak pernah leak. Kalau leak? Gimanalah.
• "Frontend validasi cukup" → asumsi: user pake browser lo. Kalau curl?
• "Library populer safe" → asumsi: maintainer jujur. Kalau account di-hijack?
• "Log gak sensitif" → asumsi: log gak akan di-baca attacker. Kalau breach?
• "2FA = selesai" → asumsi: 2FA gak bisa di-bypass. Kalau phishing?

Tiap asumsi itu attack surface. Tiap asumsi yang lo gak explicitly identify = blind spot. Attacker gak nyerang teknologi lo. Attacker nyerang asumsi lo.

---

Penutup yang Jujur

Gue gak nulis ini sebagai "5 asumsi yang bikin lo kena hack" - itu template thinking. Gue nulis ini karena 5 asumsi itu yang gue temui berulang-ulang di audit, dan tiap kali asumsi-nya di-falsify, sistem-nya jatuh. Bukan karena code-nya jelek. Karena dev-nya yakin asumsi-nya valid, padahal gak pernah di-test.

Filosofi yang gue bawa sekarang tiap nulis code: assume lo udah kena hack. Mau ngapa? Itu mindset "assume breach" yang senior security engineer pegang. Lo gak design buat "ng halau attacker" - lo design buat "ngurangin dampak kalau attacker udah masuk." Encrypt data at rest buat kalau DB di-dump. Short-lived token buat kalau token di-steal. Audit log immutable buat kalau attacker ubah data. Rate limit buat kalau credential bocor.

Kalau lo masih mikir "security = implementasi bcrypt + JWT + OWASP checklist," lo baru garuk permukaan. Checklist itu starting point, bukan goal. Yang penting: paham asumsi lo, dan tau cara test kalo asumsi lo salah.