mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 13:44:56 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
223 lines
7.7 KiB
Python
223 lines
7.7 KiB
Python
#!/usr/bin/env python3
|
|
"""OpenVAS/GVM authenticated vulnerability scan orchestration agent."""
|
|
|
|
import json
|
|
import argparse
|
|
import xml.etree.ElementTree as ET
|
|
from datetime import datetime
|
|
|
|
try:
|
|
from gvm.connections import UnixSocketConnection
|
|
from gvm.protocols.gmp import Gmp
|
|
from gvm.transforms import EtreeTransform
|
|
except ImportError:
|
|
Gmp = None
|
|
|
|
|
|
def connect_gvm(socket_path, username, password):
|
|
"""Connect to GVM daemon via Unix socket."""
|
|
if Gmp is None:
|
|
return None, "Install: pip install python-gvm"
|
|
connection = UnixSocketConnection(path=socket_path)
|
|
transform = EtreeTransform()
|
|
gmp = Gmp(connection=connection, transform=transform)
|
|
gmp.authenticate(username, password)
|
|
return gmp, None
|
|
|
|
|
|
def list_scan_configs(gmp):
|
|
"""List available scan configurations."""
|
|
response = gmp.get_scan_configs()
|
|
configs = []
|
|
for config in response.findall(".//config"):
|
|
configs.append({
|
|
"id": config.get("id"),
|
|
"name": config.findtext("name", ""),
|
|
"type": config.findtext("type", ""),
|
|
"family_count": config.findtext("family_count/growing", ""),
|
|
})
|
|
return configs
|
|
|
|
|
|
def list_credentials(gmp):
|
|
"""List configured scan credentials."""
|
|
response = gmp.get_credentials()
|
|
creds = []
|
|
for cred in response.findall(".//credential"):
|
|
creds.append({
|
|
"id": cred.get("id"),
|
|
"name": cred.findtext("name", ""),
|
|
"type": cred.findtext("type", ""),
|
|
"login": cred.findtext("login", ""),
|
|
})
|
|
return creds
|
|
|
|
|
|
def create_ssh_credential(gmp, name, login, password):
|
|
"""Create SSH credential for authenticated Linux scans."""
|
|
response = gmp.create_credential(
|
|
name=name,
|
|
credential_type=gmp.types.CredentialType.USERNAME_PASSWORD,
|
|
login=login,
|
|
password=password,
|
|
)
|
|
return response.get("id")
|
|
|
|
|
|
def create_target(gmp, name, hosts, ssh_cred_id=None, smb_cred_id=None, port_list_id=None):
|
|
"""Create scan target with optional credentials."""
|
|
kwargs = {"name": name, "hosts": hosts}
|
|
if ssh_cred_id:
|
|
kwargs["ssh_credential_id"] = ssh_cred_id
|
|
kwargs["ssh_credential_port"] = 22
|
|
if smb_cred_id:
|
|
kwargs["smb_credential_id"] = smb_cred_id
|
|
if port_list_id:
|
|
kwargs["port_list_id"] = port_list_id
|
|
response = gmp.create_target(**kwargs)
|
|
return response.get("id")
|
|
|
|
|
|
def create_and_start_task(gmp, name, target_id, config_id, scanner_id):
|
|
"""Create and start a scan task."""
|
|
response = gmp.create_task(
|
|
name=name,
|
|
config_id=config_id,
|
|
target_id=target_id,
|
|
scanner_id=scanner_id,
|
|
)
|
|
task_id = response.get("id")
|
|
gmp.start_task(task_id)
|
|
return task_id
|
|
|
|
|
|
def get_task_status(gmp, task_id):
|
|
"""Check scan task progress and status."""
|
|
response = gmp.get_task(task_id)
|
|
task = response.find(".//task")
|
|
if task is None:
|
|
return {"error": "Task not found"}
|
|
return {
|
|
"id": task_id,
|
|
"name": task.findtext("name", ""),
|
|
"status": task.findtext("status", ""),
|
|
"progress": task.findtext("progress", "0"),
|
|
"report_id": task.find(".//last_report/report").get("id", "") if task.find(".//last_report/report") is not None else "",
|
|
}
|
|
|
|
|
|
def get_report_results(gmp, report_id, min_qod=70):
|
|
"""Fetch vulnerability results from a completed scan report."""
|
|
response = gmp.get_report(
|
|
report_id,
|
|
filter_string=f"min_qod={min_qod} sort-reverse=severity",
|
|
details=True,
|
|
)
|
|
results = []
|
|
for result in response.findall(".//result"):
|
|
nvt = result.find("nvt")
|
|
results.append({
|
|
"name": nvt.findtext("name", "") if nvt is not None else "",
|
|
"oid": nvt.get("oid", "") if nvt is not None else "",
|
|
"host": result.findtext("host", ""),
|
|
"port": result.findtext("port", ""),
|
|
"severity": result.findtext("severity", "0"),
|
|
"threat": result.findtext("threat", ""),
|
|
"qod": result.findtext("qod/value", ""),
|
|
"description": result.findtext("description", "")[:200],
|
|
})
|
|
return results
|
|
|
|
|
|
def parse_openvas_xml_report(xml_path):
|
|
"""Parse an exported OpenVAS XML report file."""
|
|
tree = ET.parse(xml_path)
|
|
root = tree.getroot()
|
|
results = []
|
|
for result in root.findall(".//result"):
|
|
nvt = result.find("nvt")
|
|
results.append({
|
|
"name": nvt.findtext("name", "") if nvt is not None else "",
|
|
"host": result.findtext("host", ""),
|
|
"port": result.findtext("port", ""),
|
|
"severity": float(result.findtext("severity", "0")),
|
|
"threat": result.findtext("threat", ""),
|
|
"description": result.findtext("description", "")[:200],
|
|
})
|
|
results.sort(key=lambda x: x["severity"], reverse=True)
|
|
return results
|
|
|
|
|
|
def run_audit(args):
|
|
"""Execute OpenVAS scan audit and analysis."""
|
|
print(f"\n{'='*60}")
|
|
print(f" OPENVAS AUTHENTICATED SCAN AUDIT")
|
|
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
|
print(f"{'='*60}\n")
|
|
|
|
report = {}
|
|
|
|
if args.xml_report:
|
|
results = parse_openvas_xml_report(args.xml_report)
|
|
report["vulnerabilities"] = results
|
|
severity_counts = {"High": 0, "Medium": 0, "Low": 0, "Log": 0}
|
|
for r in results:
|
|
threat = r.get("threat", "Log")
|
|
severity_counts[threat] = severity_counts.get(threat, 0) + 1
|
|
report["severity_distribution"] = severity_counts
|
|
print(f"--- SCAN RESULTS ({len(results)} vulnerabilities) ---")
|
|
print(f" High: {severity_counts['High']} | Medium: {severity_counts['Medium']} | "
|
|
f"Low: {severity_counts['Low']} | Log: {severity_counts['Log']}")
|
|
print(f"\n--- TOP VULNERABILITIES ---")
|
|
for r in results[:15]:
|
|
print(f" [{r['threat']}] {r['host']}:{r['port']} — {r['name'][:70]}")
|
|
|
|
elif args.socket and args.gvm_user and args.gvm_pass:
|
|
gmp, error = connect_gvm(args.socket, args.gvm_user, args.gvm_pass)
|
|
if error:
|
|
print(f"ERROR: {error}")
|
|
return {"error": error}
|
|
|
|
configs = list_scan_configs(gmp)
|
|
report["scan_configs"] = configs
|
|
print(f"--- SCAN CONFIGS ({len(configs)}) ---")
|
|
for c in configs[:10]:
|
|
print(f" {c['name']} ({c['id'][:8]}...)")
|
|
|
|
creds = list_credentials(gmp)
|
|
report["credentials"] = creds
|
|
print(f"\n--- CREDENTIALS ({len(creds)}) ---")
|
|
for c in creds[:10]:
|
|
print(f" {c['name']}: type={c['type']} login={c['login']}")
|
|
|
|
if args.task_id:
|
|
status = get_task_status(gmp, args.task_id)
|
|
report["task_status"] = status
|
|
print(f"\n--- TASK STATUS ---")
|
|
print(f" {status.get('name','')}: {status.get('status','')} "
|
|
f"({status.get('progress','')}%)")
|
|
|
|
return report
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="OpenVAS Authenticated Scan Agent")
|
|
parser.add_argument("--socket", default="/run/gvmd/gvmd.sock",
|
|
help="GVM Unix socket path")
|
|
parser.add_argument("--gvm-user", help="GVM admin username")
|
|
parser.add_argument("--gvm-pass", help="GVM admin password")
|
|
parser.add_argument("--task-id", help="Existing task ID to check status")
|
|
parser.add_argument("--xml-report", help="OpenVAS XML report file to parse")
|
|
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()
|