Lewati ke konten utama

Mencegah Serangan Injeksi SQL/NoSQL di MongoDB

Amankan MongoDB dari injeksi NoSQL dengan memvalidasi input, mengamankan kueri, dan menerapkan defense-in-depth. Pelajari pola serangan dan pencegahannya dalam panduan ini.
· 6 mnt Baca

Jelajahi bersama AI

Aplikasi MongoDB menghadapi risiko keamanan serius ketika input pengguna tidak divalidasi. Serangan injeksi NoSQL dapat diam-diam membobol basis data Anda, mengekspos data sensitif, dan mengompromikan integritas sistem. Panduan ini menunjukkan strategi defensif yang telah terbukti untuk membersihkan input, mengamankan kueri basis data, dan membangun perlindungan tangguh terhadap ancaman berbasis injeksi.

Apa itu Injeksi NoSQL?

Injeksi NoSQL terjadi ketika penyerang mengeksploitasi input pengguna yang tidak divalidasi dengan baik untuk memanipulasi logika kueri basis data. Dengan menyuntikkan payload berbahaya, penyerang dapat melewati mekanisme autentikasi, mengekstrak data yang tidak berizin, atau mengakali kontrol keamanan aplikasi.

Berbeda dengan injeksi SQL, yang mengeksploitasi kerentanan dalam konstruksi kueri berbasis string, injeksi NoSQL memanfaatkan struktur data yang fleksibel dan kueri dinamis. Hal ini sangat berbahaya ketika aplikasi menerima input bertipe longgar seperti interface{} atau map[string]interface{} tanpa validasi yang tepat.

Mengapa MongoDB Berbeda

Kueri MongoDB dibangun menggunakan objek BSON (Binary JSON)—pasangan kunci-nilai terstruktur—bukan string mentah. Desain ini menghindari banyak risiko injeksi tradisional karena kueri tidak disusun melalui penggabungan string.

Namun, jika input pengguna disisipkan langsung ke dalam objek BSON ini tanpa validasi yang tepat, penyerang dapat menyuntikkan operator MongoDB seperti $ne, $gt, atau $or untuk mengubah logika kueri.

Contoh: injeksi operator di Go

filter := bson.M{"name": inputName}
collection.Find(ctx, filter)

Jika inputName adalah string biasa seperti "Joe", itu aman. Namun jika kode Anda mengizinkan map[string]interface{} atau JSON mentah, penyerang bisa menyuntikkan objek operator seperti:

{ "$ne": null }

Payload ini mengubah logika kueri, mencocokkan dokumen apa pun di mana name ada alih-alih memfilter nilai tertentu—secara efektif mengakali kontrol akses aplikasi yang dimaksudkan..

Mengenali Pola Tidak Aman dan Jebakan Umum

1. Kepercayaan implisit pada body permintaan

Parsing langsung body permintaan ke dalam peta BSON menciptakan jalur injeksi di mana penyerang dapat menanamkan operator kueri berbahaya dan konstruksi logis kompleks langsung ke dalam operasi basis data.

// Unsafe
var filter bson.M
_ = json.NewDecoder(req.Body).Decode(&filter)

Sebagai gantinya, parse hanya field dan tipe yang dikenal:

type QueryInput struct {
    Name string json:"name" validate:"required"
}

2. Menerima tipe yang longgar

Kerentanan injeksi sering muncul ketika API menerima tipe data yang terlalu permisif seperti interface{} atau peta generik. Struktur fleksibel ini dapat menyimpan operator MongoDB tersisip atau konstruksi objek berbahaya yang mengakali logika kueri yang dimaksudkan.

Minimalkan penggunaan tipe longgar kecuali benar-benar diperlukan dan terapkan validasi ketat ketika tidak terhindarkan. Sebagai gantinya, definisikan struktur data eksplisit yang sesuai dengan format input yang diharapkan dan batasi nilai yang dapat diterima.

3. JSON dalam string kueri atau operator kueri

API yang mengekspos kemampuan pemfilteran dinamis melalui parameter kueri URL atau endpoint pencarian menjadi permukaan serangan yang menarik. Penyerang sering menargetkan antarmuka ini dengan menanamkan operator berkode JSON dan logika kondisional langsung ke string kueri. Ini mengubah parameter filter yang sah menjadi operasi basis data berbahaya:

GET /search?filter={"price":{"$gt":0}}

Tanpa validasi input yang ketat, pendekatan ini memungkinkan penyerang memanipulasi struktur kueri dan mengakali kontrol keamanan, yang berpotensi mengekspos data tanpa izin atau meningkatkan hak akses melampaui tingkat yang dimaksudkan.

Mitigasi:

  • Terapkan allowlist field dan operator untuk membatasi parameter kueri pada nilai yang telah ditentukan dan aman.
  • Bungkus secara eksplisit semua nilai yang diberikan pengguna dalam operator $eq saat menyusun filter basis data guna mencegah injeksi operator alternatif.

4. Memperluas kueri logis dengan injeksi

Aplikasi yang mengizinkan kendali pengguna atas operator logis seperti $or menciptakan peluang untuk serangan perluasan kueri. Penyerang dapat menyuntikkan ekspresi kondisional tambahan ke dalam operator ini, secara fundamental mengubah semantik kueri dan berpotensi mengakali pemeriksaan autentikasi atau pembatasan akses data. 

filter := bson.M{
  "$or": []bson.M{
    {"role": "user"},
    {"active": true},
  },
}

Jika input pengguna secara langsung memanipulasi klausul $or, penyerang dapat menyisipkan kondisi yang tidak berizin:

{ "$or": [ {"role": "user"}, {"active": true}, {"isAdmin": true} ] }

Kueri yang dimodifikasi ini dapat mengakali kontrol akses berbasis peran, berpotensi mengekspos data administratif atau memberikan hak istimewa yang lebih tinggi kepada pengguna yang tidak berizin. Cegah modifikasi dinamis terhadap operator logis dengan menerapkan validasi input yang ketat dan menghindari kendali pengguna langsung atas struktur kueri. 

GET /search?filter={"price":{"$gt":0}}

Tanpa validasi input yang ketat, pendekatan ini memungkinkan penyerang memanipulasi struktur kueri dan mengakali kontrol keamanan, yang berpotensi mengekspos data tanpa izin. 

Mitigasi:

  • Terapkan allowlist untuk field dan operator yang diizinkan, tolak parameter kueri apa pun di luar batasan yang telah ditetapkan ini.
  • Terapkan pencocokan kesetaraan eksplisit dengan membungkus semua input pengguna dalam operator $eq untuk mencegah substitusi operator pembanding atau logis.

Fitur Eksekusi JavaScript

MongoDB menyediakan beberapa kemampuan eksekusi JavaScript sisi server yang memperkenalkan potensi risiko keamanan, termasuk:

Fitur-fitur ini menciptakan paparan keamanan yang signifikan dan sebaiknya dihindari kecuali ada kebutuhan bisnis kritis yang menuntut penggunaannya. Untuk mencegah eksploitasi, nonaktifkan scripting di konfigurasi MongoDB:

Untuk mongod:

--noscripting

Atau melalui file konfigurasi:

security:
  javascriptEnabled: false

Terapkan konfigurasi yang sama pada r mongos dalam deployment terpartisi (sharded).

Operator kueri native MongoDB menyediakan fungsionalitas komprehensif yang menghilangkan kebutuhan eksekusi JavaScript di hampir semua use case. Sepenuhnya hindari klausul $where kecuali Anda memiliki kendali absolut atas validasi input dan konteks eksekusi.

Cara Mencegah Injeksi NoSQL

1. Validasi input secara ketat

Terapkan validasi tipe yang ketat yang hanya menerima tipe data primitif yang diharapkan seperti string, integer, atau boolean. Tolak objek bertingkat, array, atau nama field yang tidak dikenali yang bisa berisi operasi tersisip atau konstruksi berbahaya.

type LoginInput struct {
    Username string json:"username" validate:"required,alphanum"
    Password string json:"password" validate:"required,min=8"
}

2. Jangan mempercayai struktur kueri dari pengguna

Susun semua kueri basis data menggunakan pemetaan field yang telah ditentukan dan template kueri yang dikendalikan aplikasi. Larang input pengguna memengaruhi arsitektur kueri, operator logis, atau struktur kondisional yang dapat membelokkan pola akses data yang dimaksudkan.

filter := bson.M{
    "username": input.Username,
    "password": input.Password,
}

Hindari:

// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)

Sebagian besar driver MongoDB menyediakan penyusun kueri bertipe kuat yang menegakkan konstruksi kueri terstruktur dan mencegah kerentanan injeksi yang tidak disengaja. Manfaatkan antarmuka native ini alih-alih mengekspos peta kueri mentah atau objek BSON melalui endpoint aplikasi.

filter := bson.M{
    "username": input.Username,
    "password": input.Password,
}

Hindari:

// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)

3. Blokir injeksi operator MongoDB

Cegah input yang dikendalikan pengguna berfungsi sebagai operator kueri atau konstruksi logis. Perlakukan semua data pengguna sebagai nilai literal, bukan komponen kueri yang dapat dieksekusi.

Alih-alih:

filter := bson.M{
    "status": input.Status,
}

Gunakan:

filter := bson.M{
    "status": bson.M{"$eq": input.Status},
}

Pendekatan ini menegakkan pencocokan kesetaraan ketat dan mencegah eksekusi operator yang disuntikkan seperti $ne, $in, atau $regex atau modifier logis lain yang dapat mengakali logika kueri yang dimaksudkan.

4. Gunakan hak istimewa minimum untuk pengguna basis data

Konfigurasikan koneksi basis data aplikasi dengan akun pengguna yang hanya memiliki izin minimum yang diperlukan untuk operasi yang dimaksud. Hindari menggunakan kredensial tingkat admin dari konfigurasi aplikasi untuk mencegah potensi kerusakan dari serangan injeksi yang berhasil.

5. Pantau dan uji

Terapkan pencatatan yang komprehensif untuk mendeteksi pola kueri yang tidak biasa dan tetapkan protokol pengujian keamanan rutin. Validasi keamanan endpoint dengan mencoba serangan injeksi menggunakan payload yang salah format seperti:

{ "$ne": null }

Verifikasi bahwa aplikasi menolaknya.

Kasus uji yang perlu dipertimbangkan:

  • Objek alih-alih string: { "username": { "$ne": null } }
  • Array alih-alih skalar: { "roles": [ { "$gt": "" } ] }
  • Operator sebagai nilai kueri: { "field": { "$regex": ".*" } }

Daftar Periksa Ringkasan

  • Validasi input: Terapkan tipe data yang ketat, validasi format, dan tolak field yang tidak terduga.
  • Konstruksi kueri: Susun semua kueri menggunakan skema yang telah ditentukan dan template yang dikendalikan aplikasi
  • Perlindungan operator: Blokir operator MongoDB dalam input pengguna dengan membungkus nilai dalam $eq atau menggunakan API bertipe.
  • JavaScript sisi server: Hilangkan klausul $where dan nonaktifkan eksekusi JavaScript dalam konfigurasi produksi.
  • Kontrol akses DB: Konfigurasikan koneksi aplikasi dengan izin minimum yang diperlukan, hindari kredensial administratif.
  • Pengujian dan pemantauan: Lakukan pengujian injeksi secara rutin dan terapkan pencatatan untuk pola kueri yang anomalis.

Pemikiran Akhir

Kerentanan injeksi NoSQL sepenuhnya dapat dicegah melalui praktik pengkodean aman yang disiplin. Dengan menerapkan validasi input yang ketat, konstruksi kueri terstruktur, dan kontrol keamanan defense-in-depth, pengembang dapat mempertahankan fleksibilitas dan kinerja aplikasi sekaligus meniadakan vektor serangan injeksi.

Keberhasilan menuntut pemahaman alur data aplikasi Anda secara menyeluruh—dari parsing permintaan awal hingga eksekusi kueri akhir. Tetapkan pendekatan zero-trust terhadap semua sumber input, terapkan validasi di batas sistem, dan utamakan prinsip pemrograman defensif di seluruh tumpukan teknologi Anda.

FAQs

Mengapa injeksi NoSQL berisiko jika MongoDB menggunakan BSON alih-alih string

Injeksi masih dapat terjadi sebelum objek BSON dibangun. Jika input pengguna diurai menjadi tipe fleksibel seperti map[string]interface{} atau interface{} tanpa validasi, penyerang dapat menyuntikkan operator MongoDB seperti $ne atau $or dan memanipulasi logika kueri.

Apakah aman mendekode body permintaan langsung ke bson.M atau map[string]interface{}?

Tidak. Ini memungkinkan pengguna menyuntikkan operator kueri sewenang-wenang. Selalu petakan data permintaan ke tipe ketat (mis., struct Go) dan validasi input sebelum membangun kueri.

Apa masalahnya menggunakan $where jika input sudah divalidasi?

Tidak juga. $where mengeksekusi JavaScript di server. Kesalahan kecil dalam escaping atau validasi dapat menyebabkan injeksi kode. Lebih aman sepenuhnya menghindari $where atau menonaktifkan scripting dalam konfigurasi MongoDB Anda.

Bagaimana cara menguji apakah endpoint saya rentan terhadap injeksi NoSQL?

Coba menyuntikkan payload seperti:

{ "username": { "$ne": null } }

Jika endpoint mengembalikan respons valid atau mengakali logika (mis., login), input tidak divalidasi atau dibatasi dengan benar.

Apa cara terbaik untuk membangun kueri secara aman di Go?

Gunakan struct bertipe untuk input, hindari decoding ke peta generik, dan bungkus nilai dalam $eq saat diperlukan. Jangan pernah membiarkan pengguna mendefinisikan operator atau menyuntikkan bagian kueri secara langsung.

Topik

Terkait

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

blogs

Spaghetti Plot dan Jalur Badai

blogs

Tutorial Korelasi di R