mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-18 13:39:40 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Authenticated vulnerability scan orchestration agent using Nessus API."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
import requests
|
||||
import urllib3
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
except ImportError:
|
||||
print("Install: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class NessusClient:
|
||||
"""Client for Tenable Nessus REST API."""
|
||||
|
||||
def __init__(self, url, access_key, secret_key):
|
||||
self.base_url = url.rstrip("/")
|
||||
self.headers = {
|
||||
"X-ApiKeys": f"accessKey={access_key}; secretKey={secret_key}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
def _get(self, path, params=None):
|
||||
resp = requests.get(f"{self.base_url}{path}", headers=self.headers,
|
||||
params=params, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def _post(self, path, data=None):
|
||||
resp = requests.post(f"{self.base_url}{path}", headers=self.headers,
|
||||
json=data, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def list_scans(self):
|
||||
return self._get("/scans").get("scans", [])
|
||||
|
||||
def get_scan_details(self, scan_id):
|
||||
return self._get(f"/scans/{scan_id}")
|
||||
|
||||
def list_policies(self):
|
||||
return self._get("/policies").get("policies", [])
|
||||
|
||||
def list_credentials(self):
|
||||
return self._get("/credentials").get("credentials", [])
|
||||
|
||||
def get_scan_results(self, scan_id):
|
||||
details = self.get_scan_details(scan_id)
|
||||
hosts = details.get("hosts", [])
|
||||
vulns = details.get("vulnerabilities", [])
|
||||
return {"hosts": hosts, "vulnerabilities": vulns, "info": details.get("info", {})}
|
||||
|
||||
def get_host_vulnerabilities(self, scan_id, host_id):
|
||||
return self._get(f"/scans/{scan_id}/hosts/{host_id}")
|
||||
|
||||
def export_scan(self, scan_id, fmt="nessus"):
|
||||
data = {"format": fmt}
|
||||
resp = self._post(f"/scans/{scan_id}/export", data)
|
||||
return resp.get("file", 0)
|
||||
|
||||
|
||||
def analyze_scan_results(results):
|
||||
"""Analyze scan results and categorize findings."""
|
||||
vulns = results.get("vulnerabilities", [])
|
||||
severity_map = {0: "Info", 1: "Low", 2: "Medium", 3: "High", 4: "Critical"}
|
||||
severity_counts = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0, "Info": 0}
|
||||
|
||||
categorized = []
|
||||
for v in vulns:
|
||||
sev = severity_map.get(v.get("severity", 0), "Info")
|
||||
severity_counts[sev] += 1
|
||||
categorized.append({
|
||||
"plugin_id": v.get("plugin_id", 0),
|
||||
"plugin_name": v.get("plugin_name", ""),
|
||||
"severity": sev,
|
||||
"severity_index": v.get("severity", 0),
|
||||
"count": v.get("count", 0),
|
||||
"family": v.get("plugin_family", ""),
|
||||
})
|
||||
|
||||
categorized.sort(key=lambda x: x["severity_index"], reverse=True)
|
||||
return {"severity_counts": severity_counts, "vulnerabilities": categorized}
|
||||
|
||||
|
||||
def audit_credential_coverage(results):
|
||||
"""Check if authenticated scan achieved credential coverage."""
|
||||
findings = []
|
||||
hosts = results.get("hosts", [])
|
||||
for host in hosts:
|
||||
host_info = host.get("info", {})
|
||||
credentialed = host.get("credentialed_checks_running", "")
|
||||
if not credentialed or credentialed == "no":
|
||||
findings.append({
|
||||
"host": host.get("hostname", host.get("host_id", "")),
|
||||
"issue": "Credentialed checks not running — scan is unauthenticated",
|
||||
"severity": "HIGH",
|
||||
"detail": "Configure valid credentials for this host",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def compare_auth_vs_unauth(auth_results, unauth_results):
|
||||
"""Compare authenticated vs unauthenticated scan finding counts."""
|
||||
auth_vulns = len(auth_results.get("vulnerabilities", []))
|
||||
unauth_vulns = len(unauth_results.get("vulnerabilities", []))
|
||||
improvement = ((auth_vulns - unauth_vulns) / max(unauth_vulns, 1)) * 100
|
||||
return {
|
||||
"authenticated_findings": auth_vulns,
|
||||
"unauthenticated_findings": unauth_vulns,
|
||||
"improvement_pct": round(improvement, 1),
|
||||
"additional_findings": auth_vulns - unauth_vulns,
|
||||
}
|
||||
|
||||
|
||||
def run_audit(args):
|
||||
"""Execute authenticated vulnerability scan audit."""
|
||||
print(f"\n{'='*60}")
|
||||
print(f" AUTHENTICATED VULNERABILITY SCAN AUDIT")
|
||||
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
client = NessusClient(args.nessus_url, args.access_key, args.secret_key)
|
||||
report = {}
|
||||
|
||||
scans = client.list_scans()
|
||||
report["total_scans"] = len(scans) if scans else 0
|
||||
print(f"--- AVAILABLE SCANS ({report['total_scans']}) ---")
|
||||
for s in (scans or [])[:10]:
|
||||
print(f" [{s.get('status','')}] {s.get('name','')}: {s.get('id','')}")
|
||||
|
||||
if args.scan_id:
|
||||
results = client.get_scan_results(args.scan_id)
|
||||
analysis = analyze_scan_results(results)
|
||||
report["analysis"] = analysis
|
||||
counts = analysis["severity_counts"]
|
||||
print(f"\n--- SCAN RESULTS (ID: {args.scan_id}) ---")
|
||||
print(f" Critical: {counts['Critical']} | High: {counts['High']} | "
|
||||
f"Medium: {counts['Medium']} | Low: {counts['Low']}")
|
||||
print(f"\n--- TOP VULNERABILITIES ---")
|
||||
for v in analysis["vulnerabilities"][:15]:
|
||||
print(f" [{v['severity']}] {v['plugin_name'][:70]} (x{v['count']})")
|
||||
|
||||
cred_check = audit_credential_coverage(results)
|
||||
report["credential_coverage"] = cred_check
|
||||
if cred_check:
|
||||
print(f"\n--- CREDENTIAL COVERAGE ISSUES ({len(cred_check)}) ---")
|
||||
for c in cred_check:
|
||||
print(f" [{c['severity']}] {c['host']}: {c['issue']}")
|
||||
else:
|
||||
print(f"\n Credential coverage: All hosts authenticated")
|
||||
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Authenticated Vulnerability Scan Agent")
|
||||
parser.add_argument("--nessus-url", required=True, help="Nessus server URL")
|
||||
parser.add_argument("--access-key", required=True, help="Nessus API access key")
|
||||
parser.add_argument("--secret-key", required=True, help="Nessus API secret key")
|
||||
parser.add_argument("--scan-id", type=int, help="Scan ID to analyze results")
|
||||
parser.add_argument("--output", help="Save report to JSON file")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = run_audit(args)
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
print(f"\n[+] Report saved to {args.output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user