CODEBOOK
Website Platform Belajar Dan Edukasi
By Shadownex 2025-2026
← Kembali ke Katalog Lab
NoSQL InjectionUNSOLVEDReward: +100 XP

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": ""}`.

TARGET OBJECTIVE & BRIEFING

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.

PENTESTING METHODOLOGY
1. Buka API client (Burp Suite / Postman / Lab Console).
2. Ubah Content-Type header menjadi `application/json`.
3. Kirimkan JSON request body: `{"email": "admin@codebook.com", "password": {"$gt": ""}}`.
4. Server mengembalikan response sukses berstatus Administrator beserta Flag.
CODE SECURITY INSPECTION

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' });
});