mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +03:00
27c6414ca5
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
169 lines
5.9 KiB
Python
169 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Vulnerability Scanning Workflow Agent - Automates scan orchestration and prioritization."""
|
|
|
|
import json
|
|
import logging
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
import requests
|
|
import nmap
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def run_nmap_vuln_scan(targets, ports="1-1024"):
|
|
"""Run Nmap vulnerability scan against target hosts."""
|
|
scanner = nmap.PortScanner()
|
|
logger.info("Starting Nmap vuln scan on %s ports %s", targets, ports)
|
|
scanner.scan(hosts=targets, ports=ports, arguments="-sV --script=vulners,vulscan")
|
|
results = []
|
|
for host in scanner.all_hosts():
|
|
for proto in scanner[host].all_protocols():
|
|
for port in scanner[host][proto]:
|
|
service = scanner[host][proto][port]
|
|
results.append({
|
|
"host": host,
|
|
"port": port,
|
|
"protocol": proto,
|
|
"state": service["state"],
|
|
"service": service.get("name", ""),
|
|
"version": service.get("version", ""),
|
|
"scripts": service.get("script", {}),
|
|
})
|
|
logger.info("Nmap scan complete: %d service entries", len(results))
|
|
return results
|
|
|
|
|
|
def fetch_cisa_kev():
|
|
"""Fetch the CISA Known Exploited Vulnerabilities catalog."""
|
|
url = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
|
|
resp = requests.get(url, timeout=30)
|
|
resp.raise_for_status()
|
|
kev_data = resp.json()
|
|
kev_set = {v["cveID"] for v in kev_data["vulnerabilities"]}
|
|
logger.info("Loaded %d CISA KEV entries", len(kev_set))
|
|
return kev_set
|
|
|
|
|
|
def launch_nessus_scan(nessus_url, api_keys, scan_name, targets):
|
|
"""Launch a vulnerability scan via Nessus REST API."""
|
|
headers = {"X-ApiKeys": api_keys, "Content-Type": "application/json"}
|
|
scan_config = {
|
|
"uuid": "advanced",
|
|
"settings": {
|
|
"name": scan_name,
|
|
"text_targets": targets,
|
|
"launch": "ON_DEMAND",
|
|
"enabled": True,
|
|
},
|
|
}
|
|
resp = requests.post(
|
|
f"{nessus_url}/scans", headers=headers, json=scan_config, verify=False, timeout=30
|
|
)
|
|
resp.raise_for_status()
|
|
scan_id = resp.json()["scan"]["id"]
|
|
logger.info("Nessus scan created: ID %d", scan_id)
|
|
|
|
requests.post(
|
|
f"{nessus_url}/scans/{scan_id}/launch", headers=headers, verify=False, timeout=30
|
|
)
|
|
logger.info("Nessus scan %d launched", scan_id)
|
|
return scan_id
|
|
|
|
|
|
def prioritize_vulnerabilities(vulns, kev_set, asset_criticality_map):
|
|
"""Apply risk-based prioritization to vulnerability findings."""
|
|
for vuln in vulns:
|
|
cvss = vuln.get("cvss", 0.0)
|
|
cve = vuln.get("cve", "")
|
|
host = vuln.get("host", "")
|
|
criticality = asset_criticality_map.get(host, 1.0)
|
|
|
|
risk_score = cvss * criticality
|
|
if cve in kev_set:
|
|
risk_score *= 1.5
|
|
vuln["kev"] = True
|
|
else:
|
|
vuln["kev"] = False
|
|
|
|
vuln["risk_score"] = round(risk_score, 1)
|
|
vuln["priority"] = (
|
|
"P1" if risk_score >= 13.5 else
|
|
"P2" if risk_score >= 7.0 else
|
|
"P3" if risk_score >= 4.0 else
|
|
"P4"
|
|
)
|
|
vulns.sort(key=lambda x: x["risk_score"], reverse=True)
|
|
return vulns
|
|
|
|
|
|
def create_servicenow_ticket(snow_url, token, vuln):
|
|
"""Create a ServiceNow incident ticket for a high-priority vulnerability."""
|
|
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {token}"}
|
|
ticket = {
|
|
"short_description": f"[VULN] {vuln.get('cve', 'N/A')} on {vuln['host']}",
|
|
"description": (
|
|
f"CVE: {vuln.get('cve', 'N/A')}\n"
|
|
f"CVSS: {vuln.get('cvss', 0)}\n"
|
|
f"Host: {vuln['host']}\n"
|
|
f"Risk Score: {vuln['risk_score']}\n"
|
|
f"CISA KEV: {'YES' if vuln.get('kev') else 'NO'}"
|
|
),
|
|
"urgency": "1" if vuln.get("kev") else "2",
|
|
"category": "Vulnerability",
|
|
}
|
|
resp = requests.post(
|
|
f"{snow_url}/api/now/table/incident", headers=headers, json=ticket, timeout=30
|
|
)
|
|
logger.info("ServiceNow ticket created: %s", resp.json().get("result", {}).get("number"))
|
|
return resp.json()
|
|
|
|
|
|
def generate_report(vulns):
|
|
"""Generate vulnerability scan summary report."""
|
|
p1 = [v for v in vulns if v.get("priority") == "P1"]
|
|
p2 = [v for v in vulns if v.get("priority") == "P2"]
|
|
lines = [
|
|
"VULNERABILITY SCAN REPORT",
|
|
"=" * 40,
|
|
f"Date: {datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')}",
|
|
f"Total Findings: {len(vulns)}",
|
|
f"P1 Critical: {len(p1)}",
|
|
f"P2 High: {len(p2)}",
|
|
"",
|
|
"TOP PRIORITY FINDINGS:",
|
|
]
|
|
for v in p1[:10]:
|
|
lines.append(f" {v.get('cve', 'N/A'):20s} {v['host']:15s} Score: {v['risk_score']}")
|
|
print("\n".join(lines))
|
|
return lines
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Vulnerability Scanning Workflow Agent")
|
|
parser.add_argument("--targets", required=True, help="Target hosts/CIDR")
|
|
parser.add_argument("--ports", default="1-1024", help="Port range to scan")
|
|
parser.add_argument("--nessus-url", help="Nessus API URL")
|
|
parser.add_argument("--nessus-keys", help="Nessus API keys (accessKey;secretKey)")
|
|
parser.add_argument("--output", default="vuln_report.json")
|
|
args = parser.parse_args()
|
|
|
|
kev_set = fetch_cisa_kev()
|
|
results = run_nmap_vuln_scan(args.targets, args.ports)
|
|
|
|
if args.nessus_url and args.nessus_keys:
|
|
launch_nessus_scan(args.nessus_url, args.nessus_keys, "Agent Scan", args.targets)
|
|
|
|
prioritized = prioritize_vulnerabilities(results, kev_set, {})
|
|
generate_report(prioritized)
|
|
|
|
with open(args.output, "w") as f:
|
|
json.dump(prioritized, f, indent=2)
|
|
logger.info("Report saved to %s", args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|