#!/usr/bin/env python3
# For authorized penetration testing and educational environments only.
# Usage against targets without prior mutual consent is illegal.
# It is the end user's responsibility to obey all applicable local, state and federal laws.
"""SSL stripping assessment agent using subprocess wrappers for bettercap and curl."""

import subprocess
import re
import json
import sys


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)
