mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-18 05:29:40 +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,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,60 @@
|
||||
# API Reference: SSL Stripping Assessment Agent
|
||||
|
||||
## Overview
|
||||
|
||||
Automates SSL stripping vulnerability assessment by checking HSTS headers, preload list status, redirect chains, mixed content, and security headers using curl subprocess calls.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| subprocess | stdlib | Runs curl for HTTP header inspection |
|
||||
| re | stdlib | Regex parsing of HSTS header values |
|
||||
| json | stdlib | Parses hstspreload.org API responses |
|
||||
|
||||
## External Tools Required
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| curl | HTTP/HTTPS header and content fetching |
|
||||
|
||||
## Core Functions
|
||||
|
||||
### `check_hsts_header(target_url)`
|
||||
Fetches response headers and parses Strict-Transport-Security values.
|
||||
- **Returns**: `dict` with `hsts_present`, `max_age`, `include_subdomains`, `preload`
|
||||
|
||||
### `check_hsts_preload(domain)`
|
||||
Queries the hstspreload.org API to check browser preload list inclusion.
|
||||
- **Returns**: `dict` with `status` and `preloaded` boolean
|
||||
|
||||
### `check_redirect_chain(url)`
|
||||
Follows HTTP redirects to verify HTTPS upgrade behavior.
|
||||
- **Returns**: `dict` with `initial_url`, `final_url`, `upgrades_to_https`
|
||||
|
||||
### `check_mixed_content(url)`
|
||||
Scans page HTML for HTTP resource references on HTTPS pages.
|
||||
- **Returns**: `dict` with `mixed_content_found` and `http_reference_count`
|
||||
|
||||
### `check_security_headers(url)`
|
||||
Checks for CSP, X-Content-Type-Options, X-Frame-Options, and Upgrade-Insecure-Requests.
|
||||
- **Returns**: `dict[str, bool]` - header name to presence mapping
|
||||
|
||||
### `run_assessment(targets)`
|
||||
Full assessment pipeline for a list of target domains.
|
||||
- **Parameters**: `targets` (list[str]) - domain names
|
||||
- **Returns**: `list[dict]` - per-target assessment results with `ssl_strip_risk`
|
||||
|
||||
## Risk Levels
|
||||
|
||||
| Level | Criteria |
|
||||
|-------|----------|
|
||||
| HIGH | No HSTS header present |
|
||||
| MEDIUM | HSTS present but not in preload list |
|
||||
| LOW | HSTS with preload list inclusion |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
python agent.py example.com banking.example.com api.example.com
|
||||
```
|
||||
@@ -0,0 +1,147 @@
|
||||
#!/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)
|
||||
Reference in New Issue
Block a user