Lab 9: NoSQL injection in MongoDB JSON payload allowing authentication bypass
Endpoint REST API menerima objek JSON mentah pada kolom password tanpa memastikan tipe data string, memungkinkan penggunaan operator MongoDB seperti `{"$gt": ""}`.
Objective:
Kirimkan JSON payload berisi operator query MongoDB `$gt` (Greater Than) untuk bypass verifikasi kata sandi admin.
Backend Node.js & Express menggunakan Mongoose/MongoDB driver untuk autentikasi pengguna. Kode menerima JSON body secara langsung: `User.findOne({ email: req.body.email, password: req.body.password })` Apabila penyerang mengirimkan objek JSON alih-alih string (`"password": {"$gt": ""}`), query MongoDB dievaluasi menjadi: "Cari pengguna dengan email admin yang password-nya lebih besar dari string kosong", yang selalu bernilai TRUE.
NoSQL Injection terjadi saat interpreter NoSQL mengeksekusi objek operator seperti $gt atau $ne. CodeBook mewajibkan pengecekan tipe data string dan penggunaan hash comparison bcrypt.
VULNERABLE CODE
// KODE RENTAN (Direct Body Object Pass-Through)
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
// DANGEROUS: req.body.password bisa bernilai objek {"$gt": ""}!
const user = await db.collection('users').findOne({ email, password });
if (user) return res.json({ success: true, token: user.token });
res.status(401).json({ error: 'Kredensial salah' });
});SECURE CODEBOOK IMPLEMENTATION
// KODE AMAN CODEBOOK STANDARD (Strict Type Checking & Express-Mongo-Sanitize)
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
// SAFE 1: Validasi tipe data wajib string
if (typeof email !== 'string' || typeof password !== 'string') {
return res.status(400).json({ error: 'Format input harus berupa string' });
}
// SAFE 2: Verifikasi password menggunakan bcrypt hash comparison
const user = await db.collection('users').findOne({ email });
if (user && await bcrypt.compare(password, user.passwordHash)) {
return res.json({ success: true, token: user.token });
}
res.status(401).json({ error: 'Kredensial salah' });
});