mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 13:44:56 +03:00
155 lines
5.9 KiB
Python
155 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Greenbone/OpenVAS Vulnerability Management agent - creates scan targets, executes scans, and parses reports via python-gvm GMP protocol"""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from collections import Counter, defaultdict
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from gvm.connections import UnixSocketConnection, TLSConnection
|
|
from gvm.protocols.gmp import Gmp
|
|
from gvm.transforms import EtreeTransform
|
|
from lxml import etree
|
|
HAS_GVM = True
|
|
except ImportError:
|
|
HAS_GVM = False
|
|
|
|
|
|
def load_data(path):
|
|
return json.loads(Path(path).read_text(encoding="utf-8"))
|
|
|
|
|
|
def connect_gvm(host, port=9390, socket_path="/run/gvmd/gvmd.sock", use_tls=False, username="admin", password="admin"):
|
|
"""Connect to GVM daemon and authenticate via GMP."""
|
|
if not HAS_GVM:
|
|
return None, "python-gvm not installed"
|
|
transform = EtreeTransform()
|
|
if use_tls:
|
|
conn = TLSConnection(hostname=host, port=port)
|
|
else:
|
|
conn = UnixSocketConnection(path=socket_path)
|
|
gmp = Gmp(connection=conn, transform=transform)
|
|
gmp.authenticate(username, password)
|
|
version_resp = gmp.get_version()
|
|
version = version_resp.xpath("version/text()")[0] if version_resp.xpath("version/text()") else "unknown"
|
|
return gmp, version
|
|
|
|
|
|
def create_target(gmp, name, hosts, port_list_id="33d0cd82-57c6-11e1-8ed1-406186ea4fc5"):
|
|
"""Create a scan target. Default port list is 'All IANA assigned TCP'."""
|
|
resp = gmp.create_target(name=name, hosts=hosts, port_list_id=port_list_id)
|
|
target_id = resp.get("id", "")
|
|
return target_id
|
|
|
|
|
|
def create_and_start_task(gmp, task_name, target_id, config_id="daba56c8-73ec-11df-a475-002264764cea", scanner_id="08b69003-5fc2-4037-a479-93b440211c73"):
|
|
"""Create scan task and start it. Default config is 'Full and fast', default scanner is 'OpenVAS Default'."""
|
|
resp = gmp.create_task(name=task_name, config_id=config_id, target_id=target_id, scanner_id=scanner_id)
|
|
task_id = resp.get("id", "")
|
|
gmp.start_task(task_id)
|
|
return task_id
|
|
|
|
|
|
def parse_report_xml(report_xml):
|
|
"""Parse GMP report XML into structured findings."""
|
|
findings = []
|
|
results = report_xml.findall(".//result") if report_xml is not None else []
|
|
for result in results:
|
|
host_el = result.find("host")
|
|
host = host_el.text if host_el is not None else ""
|
|
name_el = result.find("name")
|
|
name = name_el.text if name_el is not None else ""
|
|
threat_el = result.find("threat")
|
|
threat = threat_el.text if threat_el is not None else "Log"
|
|
severity_el = result.find("severity")
|
|
cvss = float(severity_el.text) if severity_el is not None and severity_el.text else 0.0
|
|
nvt = result.find("nvt")
|
|
oid = nvt.get("oid", "") if nvt is not None else ""
|
|
cve_el = nvt.find("cve") if nvt is not None else None
|
|
cve = cve_el.text if cve_el is not None and cve_el.text != "NOCVE" else ""
|
|
desc_el = result.find("description")
|
|
desc = (desc_el.text or "")[:200] if desc_el is not None else ""
|
|
sev_label = "critical" if cvss >= 9.0 else "high" if cvss >= 7.0 else "medium" if cvss >= 4.0 else "low"
|
|
findings.append({
|
|
"host": host,
|
|
"vulnerability": name,
|
|
"severity": sev_label,
|
|
"cvss": cvss,
|
|
"cve": cve,
|
|
"nvt_oid": oid,
|
|
"description": desc,
|
|
})
|
|
return findings
|
|
|
|
|
|
def analyze_offline_report(data):
|
|
"""Analyze pre-exported GVM report data (JSON format)."""
|
|
findings = []
|
|
results = data.get("results", data.get("vulnerabilities", []))
|
|
if isinstance(data, list):
|
|
results = data
|
|
for r in results:
|
|
cvss = r.get("cvss", r.get("severity_score", 0.0))
|
|
if isinstance(cvss, str):
|
|
try:
|
|
cvss = float(cvss)
|
|
except ValueError:
|
|
cvss = 0.0
|
|
sev_label = "critical" if cvss >= 9.0 else "high" if cvss >= 7.0 else "medium" if cvss >= 4.0 else "low"
|
|
findings.append({
|
|
"host": r.get("host", r.get("ip", "")),
|
|
"vulnerability": r.get("name", r.get("vulnerability", "")),
|
|
"severity": sev_label,
|
|
"cvss": cvss,
|
|
"cve": r.get("cve", r.get("cves", "")),
|
|
"nvt_oid": r.get("nvt_oid", r.get("oid", "")),
|
|
"description": (r.get("description", r.get("summary", "")) or "")[:200],
|
|
})
|
|
return findings
|
|
|
|
|
|
def generate_report(input_path):
|
|
data = load_data(input_path)
|
|
findings = analyze_offline_report(data)
|
|
sev = Counter(f["severity"] for f in findings)
|
|
host_vulns = defaultdict(int)
|
|
for f in findings:
|
|
host_vulns[f["host"]] += 1
|
|
cve_list = [f["cve"] for f in findings if f["cve"]]
|
|
findings.sort(key=lambda x: x["cvss"], reverse=True)
|
|
return {
|
|
"report": "greenbone_vulnerability_management",
|
|
"generated_at": datetime.utcnow().isoformat() + "Z",
|
|
"total_vulnerabilities": len(findings),
|
|
"severity_summary": dict(sev),
|
|
"hosts_scanned": len(host_vulns),
|
|
"host_vulnerability_counts": dict(host_vulns),
|
|
"unique_cves": len(set(cve_list)),
|
|
"top_10_findings": findings[:10],
|
|
"findings": findings,
|
|
}
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser(description="Greenbone Vulnerability Management Agent")
|
|
ap.add_argument("--input", required=True, help="Input JSON with GVM scan results")
|
|
ap.add_argument("--output", help="Output JSON report path")
|
|
ap.add_argument("--host", help="GVM host for live scan (requires python-gvm)")
|
|
ap.add_argument("--username", default="admin", help="GMP username")
|
|
ap.add_argument("--password", default="admin", help="GMP password")
|
|
args = ap.parse_args()
|
|
report = generate_report(args.input)
|
|
out = json.dumps(report, indent=2)
|
|
if args.output:
|
|
Path(args.output).write_text(out, encoding="utf-8")
|
|
print(f"Report written to {args.output}")
|
|
else:
|
|
print(out)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|