Files
Anthropic-Cybersecurity-Skills/skills/performing-ssl-stripping-attack/scripts/agent.py
T
mukul975 27c6414ca5 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
2026-03-10 21:02:12 +01:00

148 lines
5.5 KiB
Python

#!/usr/bin/env python3
"""SSL stripping assessment agent using subprocess wrappers for bettercap and curl."""
import subprocess
import re
import json
import sys
import shutil
def check_hsts_header(target_url):
"""Check HSTS header on a target URL using curl."""
result = subprocess.run(
["curl", "-sI", "--max-time", "10", target_url],
capture_output=True, text=True, timeout=15
)
headers = result.stdout
hsts_match = re.search(
r"strict-transport-security:\s*(.+)", headers, re.IGNORECASE
)
findings = {"url": target_url, "hsts_present": False, "details": {}}
if hsts_match:
hsts_value = hsts_match.group(1).strip()
findings["hsts_present"] = True
findings["details"]["raw"] = hsts_value
max_age = re.search(r"max-age=(\d+)", hsts_value)
if max_age:
findings["details"]["max_age"] = int(max_age.group(1))
findings["details"]["include_subdomains"] = "includesubdomains" in hsts_value.lower()
findings["details"]["preload"] = "preload" in hsts_value.lower()
return findings
def check_hsts_preload(domain):
"""Check if domain is in HSTS preload list via the hstspreload.org API."""
try:
result = subprocess.run(
["curl", "-s", f"https://hstspreload.org/api/v2/status?domain={domain}"],
capture_output=True, text=True, timeout=15
)
data = json.loads(result.stdout)
return {
"domain": domain,
"status": data.get("status", "unknown"),
"preloaded": data.get("status") == "preloaded",
}
except (json.JSONDecodeError, subprocess.TimeoutExpired):
return {"domain": domain, "status": "error", "preloaded": False}
def check_redirect_chain(url):
"""Follow HTTP redirects and check for HTTPS upgrade."""
result = subprocess.run(
["curl", "-sIL", "--max-time", "10", "-o", "/dev/null",
"-w", "%{redirect_url}\\n%{url_effective}\\n%{scheme}", url],
capture_output=True, text=True, timeout=15
)
lines = result.stdout.strip().split("\n")
return {
"initial_url": url,
"redirect_url": lines[0] if len(lines) > 0 else "",
"final_url": lines[1] if len(lines) > 1 else "",
"final_scheme": lines[2] if len(lines) > 2 else "",
"upgrades_to_https": lines[2] == "HTTPS" if len(lines) > 2 else False,
}
def check_mixed_content(url):
"""Fetch page and check for HTTP resources on an HTTPS page."""
result = subprocess.run(
["curl", "-s", "--max-time", "10", url],
capture_output=True, text=True, timeout=15
)
body = result.stdout
http_refs = re.findall(r'(src|href|action)=["\']http://', body, re.IGNORECASE)
return {
"url": url,
"mixed_content_found": len(http_refs) > 0,
"http_reference_count": len(http_refs),
}
def check_security_headers(url):
"""Check for key security headers that complement HSTS."""
result = subprocess.run(
["curl", "-sI", "--max-time", "10", url],
capture_output=True, text=True, timeout=15
)
headers_text = result.stdout.lower()
checks = {
"content-security-policy": "content-security-policy:" in headers_text,
"x-content-type-options": "x-content-type-options:" in headers_text,
"x-frame-options": "x-frame-options:" in headers_text,
"upgrade-insecure-requests": "upgrade-insecure-requests" in headers_text,
}
return checks
def run_assessment(targets):
"""Run full SSL stripping assessment against a list of target domains."""
results = []
for target in targets:
https_url = f"https://{target}"
http_url = f"http://{target}"
entry = {"target": target}
entry["hsts"] = check_hsts_header(https_url)
entry["preload"] = check_hsts_preload(target)
entry["redirect"] = check_redirect_chain(http_url)
entry["mixed_content"] = check_mixed_content(https_url)
entry["security_headers"] = check_security_headers(https_url)
vulnerable = (
not entry["hsts"]["hsts_present"]
or not entry["preload"]["preloaded"]
or entry["mixed_content"]["mixed_content_found"]
)
entry["ssl_strip_risk"] = "HIGH" if not entry["hsts"]["hsts_present"] else (
"MEDIUM" if not entry["preload"]["preloaded"] else "LOW"
)
results.append(entry)
return results
def print_report(results):
print("SSL Stripping Assessment Report")
print("=" * 50)
for r in results:
print(f"\nTarget: {r['target']}")
print(f" HSTS Present: {r['hsts']['hsts_present']}")
if r["hsts"]["hsts_present"]:
d = r["hsts"]["details"]
print(f" max-age: {d.get('max_age', 'N/A')}")
print(f" subdomains: {d.get('include_subdomains', False)}")
print(f" preload dir: {d.get('preload', False)}")
print(f" Preload List: {r['preload']['status']}")
print(f" HTTP->HTTPS: {r['redirect']['upgrades_to_https']}")
print(f" Mixed Content: {r['mixed_content']['http_reference_count']} refs")
print(f" SSL Strip Risk: {r['ssl_strip_risk']}")
sh = r["security_headers"]
missing = [h for h, v in sh.items() if not v]
if missing:
print(f" Missing Headers: {', '.join(missing)}")
if __name__ == "__main__":
targets = sys.argv[1:] if len(sys.argv) > 1 else ["example.com"]
results = run_assessment(targets)
print_report(results)