Keamanan JSON: Kerentanan Umum dan Cara Menghindarinya
JSON tidak berisi kode yang bisa dieksekusi, dan terhindar dari risiko external entity XML serta kejutan type coercion YAML, sehingga JSON dikenal aman untuk diurai. Tahap parsing memang sebagian besar layak mendapat reputasi itu. Kerentanan nyata ada pada apa yang dilakukan kode Anda dengan object hasil parsing setelahnya.
Prototype pollution lewat input JSON
Object JavaScript mewarisi dari rantai prototype bersama. Jika JSON tak terpercaya berisi key seperti "__proto__" dan kode Anda meng-merge-nya ke object yang ada tanpa menjaga key khusus, penyerang bisa menyuntikkan property ke Object.prototype itu sendiri. Akibatnya mengenai setiap object dalam aplikasi Anda, bukan hanya object yang menerima merge.
{
"__proto__": {
"isAdmin": true
}
}Deep-merge payload ini ke object pengguna dengan merge rekursif yang tidak menangani key __proto__, constructor, atau prototype secara khusus, dan setiap object dalam proses itu, termasuk yang tak pernah menyentuh payload ini, bisa mendapat property isAdmin bernilai true. Penyerang sudah mengeksploitasi kelas kerentanan ini di beberapa library merge/extend npm yang populer.
Cara menghindari prototype pollution
Gunakan Object.create(null) untuk map yang dibangun dari key tak terpercaya, karena tidak punya prototype yang bisa tercemar. Utamakan Map daripada object polos ketika key berasal dari input pengguna dan Anda tidak perlu menyerialisasi hasilnya ke JSON. Jika Anda harus me-deep-merge JSON tak terpercaya ke object yang ada, pakai utilitas merge yang memblokir __proto__, constructor, dan prototype sebagai key, dan periksa apakah dependensi Anda sudah menambalnya (kebanyakan library besar sudah, di versi terbaru), jangan berasumsi. Jaga dependensi tetap mutakhir: maintainer sudah berkali-kali menambal kelas kerentanan ini di berbagai package populer seiring peneliti menemukan teknik bypass baru.
Deserialisasi tidak aman di luar JSON.parse biasa
JSON.parse() biasa menghasilkan data polos: string, number, boolean, null, object polos, dan array. Ia tak bisa membangun instance kelas arbitrer atau mengeksekusi kode, berbeda dengan sebagian format serialisasi lain (pickle Python bisa mengeksekusi kode arbitrer saat deserialisasi). Risiko muncul ketika fungsi reviver atau langkah downstream merekonstruksi instance kelas atau menjalankan logika berdasarkan nilai field tak terpercaya. Contohnya, kode yang membaca field "type" dari JSON lalu memakainya untuk require() modul atau dispatch ke handler berdasarkan nama tanpa mencocokkan string itu dengan allowlist.
Validasi terhadap schema sebelum memercayai JSON tak terpercaya
JSON.parse() hanya menjamin validitas sintaksis, tidak menjamin data cocok dengan bentuk yang diharapkan kode Anda. Body request yang valid sebagai JSON tetapi tidak punya field wajib, atau berisi string di tempat number, bisa membuat kode downstream crash atau berperilaku salah tanpa error. Validasi JSON yang masuk terhadap schema (JSON Schema, Zod, Joi, atau sejenisnya) sebelum dipakai. Anda menangkap struktur cacat di batas, menolaknya dengan pesan error yang berguna daripada crash membingungkan tiga fungsi ke dalam, dan schema itu sekaligus mendokumentasikan bentuk yang diharapkan endpoint.
Checklist praktis
Validasi JSON tak terpercaya terhadap schema di batas, sebelum mencapai logika bisnis. Jangan me-deep-merge JSON tak terpercaya ke object berumur panjang tanpa utilitas merge yang memblokir key berbahaya. Hindari fungsi reviver atau dispatch dinamis berbasis field string tak terpercaya kecuali Anda mencocokkan nilainya dengan allowlist. Jaga dependensi penanganan JSON (parser, utilitas merge, validator schema) tetap mutakhir, karena peneliti terus menemukan varian baru bug ini. Tetapkan batas ukuran pada body request JSON untuk mengurangi risiko serangan resource-exhaustion lewat payload yang bersarang sangat dalam atau sangat besar.
FAQ
- Apakah JSON.parse() sendiri rentan terhadap eksekusi kode, seperti eval()?
- Tidak. JSON.parse() hanya menghasilkan struktur data polos (string, number, boolean, null, object polos, array) dan tidak pernah mengeksekusi kode, tak seperti parsing JSON berbasis eval() yang dipakai sebagian codebase sangat tua sebelum JSON.parse() native menjadi standar. JSON.parse() modern aman soal eksekusi kode; risiko yang dibahas di sini ada pada apa yang dilakukan kode Anda dengan hasil parsingnya setelahnya.
- Apa itu prototype pollution dalam istilah sederhana?
- Penyerang mengirim input (sering JSON dengan key __proto__), dan kode yang tidak menjaga nama property khusus meng-merge-nya ke sebuah object. Penyerang lalu bisa menambah atau menimpa property pada object dasar bersama yang diwarisi semua object JavaScript, dan itu memengaruhi seluruh aplikasi.
- Apakah saya butuh validasi schema jika sudah memakai TypeScript?
- Ya. Compiler TypeScript menghapus tipe, jadi tipe tidak memberi perlindungan runtime sama sekali. Tidak ada yang memeriksa payload JSON cacat atau jahat yang datang lewat HTTP kecuali Anda memvalidasinya dengan library seperti Zod, Joi, atau validator JSON Schema. TypeScript mencegah Anda menulis kode yang salah menangani bentuk yang diharapkan; ia tidak bisa memverifikasi bahwa data yang masuk cocok dengan bentuk itu.
- Apakah YAML atau XML lebih aman diurai daripada JSON?
- Tidak, keduanya punya kelas kerentanan sendiri. Parser YAML di sebagian bahasa mendukung type coercion dan tag yang bisa membangun object arbitrer kecuali Anda mengaktifkan mode "safe load" yang terbatas. Parser XML rentan serangan XML External Entity (XXE) jika ekspansi entity tidak dimatikan. Sistem tipe JSON yang lebih sederhana (tanpa tag, tanpa entity) menghapus permukaan serangan itu, tetapi risiko deserialisasi dan merging yang dibahas di sini tetap berlaku.
Coba alat ini
Artikel terkait
Apa itu JSON? Panduan Lengkap untuk Pemula →
JSON (JavaScript Object Notation) adalah format pertukaran data yang ringan, mudah dibaca manusia dan mudah diurai mesin. Pelajari sintaks, tipe data, dan struktur yang menjadi fondasi API modern.
Sejarah JSON: Dari Tahun 2000 hingga Menjadi Standar Industri →
Telusuri JSON dari ide Douglas Crockford tahun 2001, diadopsi oleh Yahoo, hingga menjadi standar ECMA-404 yang menggerakkan 90% API modern.
Panduan Lengkap JSON Schema (Draft 7) →
JSON Schema adalah standar untuk mendeskripsikan dan memvalidasi struktur JSON. Pelajari keyword inti, bangun schema API nyata, dan terapkan praktik terbaik.