To solve the lab, you'll first need to exfiltrate the value of the password reset token for the user
carlos.
Lab: Exploiting NoSQL operator injection to extract unknown fields
The user lookup functionality for this lab is powered by a MongoDB NoSQL database. It is vulnerable to NoSQL injection.
To solve the lab, log in as carlos.
Tip
Solution
-
In Burp's browser, attempt to log in to the application with username
carlosand passwordinvalid. Notice that you receive anInvalid username or passworderror message. -
In Burp, go to Proxy > HTTP history. Right-click the
POST /loginrequest and select Send to Repeater. -
In Repeater, change the value of the password parameter from
"invalid"to{"$ne":"invalid"}, then send the request. Notice that you now receive anAccount lockederror message. You can't access Carlos's account, but this response indicates that the$neoperator has been accepted and the application is vulnerable. -
In Burp's browser, attempt to reset the password for the
carlosaccount. When you submit thecarlosusername, observe that the reset mechanism involves email verification, so you can't reset the account yourself. -
In Repeater, use the
POST /loginrequest to test whether the application is vulnerable to JavaScript injection:- Add
"$where": "0"as an additional parameter in the JSON data as follows:{"username":"carlos","password":{"$ne":"invalid"}, "$where": "0"} - Send the request. Notice that you receive an
Invalid username or passworderror message. - Change
"$where": "0" to "$where": "1", then resend the request. Notice that you receive anAccount lockederror message. This indicates that the JavaScript in the$whereclause is being evaluated.
- Add
-
Right-click the request and select Send to Intruder.
-
In Intruder, construct an attack to identify all the fields on the user object:
- Update the
$whereparameter as follows:"$where":"Object.keys(this)[1].match('^.{}.*')" - Add two payload positions. The first identifies the character position number, and
the second identifies the character itself:
"$where":"Object.keys(this)[1].match('^.{§§}§§.*')" - Select Cluster bomb attack from the attack type drop-down menu.
- In the Payloads side panel, select position
1from the Payload position drop-down list, then set the Payload type to Numbers. Set the number range, for example from 0 to 20. - Select position
2from the Payload position drop-down list and make sure the Payload type is set to Simple list. Add all numbers, lower-case letters and upper-case letters as payloads. If you're using Burp Suite Professional, you can use the built-in word listsa-z,A-Z, and0-9. - Click Start attack.
- Sort the attack results by Payload 1, then Length, to identify responses with an
Account lockedmessage instead of theInvalid username or passwordmessage. Notice that the characters in the Payload 2 column spell out the name of the parameter:username. -
Repeat the above steps to identify further JSON parameters. You can do this by incrementing the index of the keys array with each attempt, for example:
"$where":"Object.keys(this)[2].match('^.{}.*')"Notice that one of the JSON parameters is for a password reset token.
- Update the
-
Test the identified password reset field name as a query parameter on different endpoints:
- In Proxy > HTTP history, identify the
GET /forgot-passwordrequest as a potentially interesting endpoint, as it relates to the password reset functionality. Right-click the request and select Send to Repeater. - In Repeater, submit an invalid field in the URL:
GET /forgot-password?foo=invalid. Notice that the response is identical to the original response. - Submit the exfiltrated name of the password reset token field in the URL:
GET /forgot-password?YOURTOKENNAME=invalid. Notice that you receive anInvalid tokenerror message. This confirms that you have the correct token name and endpoint.
- In Proxy > HTTP history, identify the
-
In Intruder, use the
POST /loginrequest to construct an attack that extracts the value of Carlos's password reset token:-
Keep the settings from your previous attack, but update the
$whereparameter as follows:"$where":"this.YOURTOKENNAME.match('^.{§§}§§.*')"Make sure that you replace
YOURTOKENNAMEwith the password reset token name that you exfiltrated in the previous step. - Click Start attack.
-
Sort the attack results by Payload 1, then Length, to identify responses with an
Account lockedmessage instead of theInvalid username or passwordmessage. Note the letters from the Payload 2 column down.
-
-
In Repeater, submit the value of the password reset token in the URL of the
GET / forgot-passwordrequest:GET /forgot-password?YOURTOKENNAME=TOKENVALUE. - Right-click the response and select Request in browser > Original session. Paste this into Burp's browser.
- Change Carlos's password, then log in as
carlosto solve the lab.