No Sql Injection

Published: April 3, 2024

Description

Can you try to get access to this website to get the flag? You can download the source here. The website is running here. Can you log in?

Web proxy

Download the challenge source to study app/utils/seed.ts and app/utils/database.ts.

Open the target site (linked in the challenge) and monitor the /api/login request in DevTools Network tab.

Email: joshiriya355@mumbama.com
Password JSON: {"$ne":"null"}

Solution

The SQL Injection for CTF guide covers NoSQL operator injection (used here) alongside classic SQL injection techniques.
  1. Step 1Submit crafted JSON
    Use the email from seed.ts and place {"$ne":"null"} as the password value. MongoDB interprets it as "password not equal to null," instantly passing the check.
    {"email":"joshiriya355@mumbama.com","password":{"$ne":"null"}}
    Learn more

    NoSQL injection exploits the fact that document databases like MongoDB accept query operators as part of the data payload itself. When an API endpoint deserializes user-supplied JSON directly into a database query object, an attacker can inject operators such as $ne (not equal), $gt (greater than), or $regex to manipulate query logic.

    The $ne operator in MongoDB means "not equal to." Sending {"password": {"$ne": "null"}} transforms the login query from "find user where password equals X" into "find user where password is not null" - which matches virtually every real account. This is the NoSQL equivalent of the classic SQL OR 1=1 bypass.

    • The vulnerability requires that the backend passes unsanitized JSON directly to the MongoDB driver.
    • The fix is to validate and whitelist input types - if a password field should be a string, reject objects.
    • ORMs and query builders with parameterized queries prevent this; raw db.collection.findOne({...userInput}) does not.
  2. Step 2Grab the token
    Inspect the /api/login response. It returns a JSON array with a base64-encoded token field.
    Learn more

    After a successful login, APIs typically return a token- commonly a JWT (JSON Web Token) or a simple base64-encoded payload - that the client attaches to subsequent requests to prove it is authenticated. Inspecting the raw response body in DevTools' Network tab (or with Burp) shows the exact structure.

    Base64 is an encoding, not encryption. It converts binary data into ASCII-safe text using 64 printable characters. It is trivially reversible and provides zero confidentiality - anything base64-encoded is effectively plaintext to anyone who looks at it. Seeing base64 in an API response is always worth decoding.

    JWTs have three base64url-encoded sections separated by dots: header, payload, and signature. Even without the secret key you can read the header and payload, which often contain user IDs, roles, and expiration times that reveal application logic.

  3. Step 3Decode the flag
    Base64-decode the token (CyberChef or base64 -d) to recover the picoCTF flag.
    echo cGljb0NURntqQBh...== | base64 -d
    Learn more

    base64 -d is the standard Linux command for decoding base64 strings. The echo pipe feeds the encoded string as stdin. Note that base64 strings may include = or == padding at the end - this is normal and needed for correct decoding.

    CyberChef's From Base64 recipe is especially handy when the output is not clean ASCII (e.g., binary data or nested encodings), as it renders the result visually and lets you chain further operations like From Hex or Gunzip in a pipeline.

    This challenge is a good reminder that sensitive data should never be embedded in tokens without encryption. Even if the flag were intended to be revealed after login, encoding it in base64 gives the illusion of protection while providing none.

Flag

picoCTF{jBhD2y7XoNzPv_1YxS9Ew5qL0uI6pasql_injection_f2f1...}

Decoding the token from /api/login yields the flag.

Want more picoCTF 2024 writeups?

Useful tools for Web Exploitation

Related reading

Do these first

What to try next