vulnerability management

Performing Authenticated Scan with OpenVAS

Configure and execute authenticated vulnerability scans using OpenVAS/Greenbone Vulnerability Management with SSH and SMB credentials for comprehensive host-level assessment.

authenticated-scancredentialed-scangreenbonegvmnetwork-securityopenvasvulnerability-scanning
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

OpenVAS (Open Vulnerability Assessment Scanner) is the scanner component of the Greenbone Vulnerability Management (GVM) framework. Authenticated scans use valid credentials (SSH for Linux, SMB for Windows, ESXi for VMware) to log into target systems, enabling detection of local vulnerabilities, missing patches, and misconfigurations that unauthenticated scans cannot identify. Authenticated scans typically find 10-50x more vulnerabilities than unauthenticated scans.

When to Use

  • When conducting security assessments that involve performing authenticated scan with openvas
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing

Prerequisites

  • GVM 22.x+ installed (gvmd, openvas-scanner, gsad, ospd-openvas)
  • PostgreSQL database configured for gvmd
  • Redis configured for openvas-scanner
  • NVT feed synchronized (greenbone-nvt-sync or greenbone-feed-sync)
  • SSH credentials for Linux targets or SMB credentials for Windows targets
  • Network access to target hosts on scan ports

Installation

Install GVM on Kali Linux / Debian

# Install GVM package
sudo apt update && sudo apt install -y gvm
 
# Run initial setup (creates admin account, syncs feeds)
sudo gvm-setup
 
# Check installation status
sudo gvm-check-setup
 
# Start all GVM services
sudo gvm-start
 
# Access Greenbone Security Assistant at https://127.0.0.1:9392

Install via Docker (Recommended for Production)

# Pull Greenbone Community Edition containers
docker pull greenbone/gvm:stable
 
# Run with docker-compose
curl -fsSL https://greenbone.github.io/docs/latest/_static/docker-compose-22.4.yml \
  -o docker-compose.yml
 
# Start the stack
docker compose -f docker-compose.yml -p greenbone-community-edition up -d
 
# Wait for feed sync (initial sync takes 15-30 minutes)
docker compose -f docker-compose.yml -p greenbone-community-edition \
  logs -f gvmd 2>&1 | grep -i "feed"

Configuring Credentials

SSH Credentials for Linux Targets

# Using gvm-cli to create SSH credential with key-based auth
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_credential>
    <name>Linux SSH Key</name>
    <type>usk</type>
    <login>scan_user</login>
    <key>
      <private><![CDATA['"$(cat /home/scan_user/.ssh/id_rsa)"']]></private>
      <phrase>key_passphrase</phrase>
    </key>
  </create_credential>'
 
# SSH credential with password authentication
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_credential>
    <name>Linux SSH Password</name>
    <type>up</type>
    <login>scan_user</login>
    <password>scan_password_here</password>
  </create_credential>'

SMB Credentials for Windows Targets

# Create SMB credential for Windows authenticated scanning
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_credential>
    <name>Windows SMB Cred</name>
    <type>up</type>
    <login>DOMAIN\scan_account</login>
    <password>smb_password_here</password>
  </create_credential>'

ESXi Credentials

# Create ESXi credential for VMware host scanning
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_credential>
    <name>ESXi Root</name>
    <type>up</type>
    <login>root</login>
    <password>esxi_password_here</password>
  </create_credential>'

Creating Scan Targets

# Create target with SSH credential (Linux hosts)
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_target>
    <name>Linux Production Servers</name>
    <hosts>192.168.1.10,192.168.1.11,192.168.1.12</hosts>
    <port_list id="33d0cd82-57c6-11e1-8ed1-406186ea4fc5"/>
    <ssh_credential id="CREDENTIAL_UUID_HERE">
      <port>22</port>
    </ssh_credential>
    <alive_test>ICMP, TCP-ACK Service and ARP Ping</alive_test>
  </create_target>'
 
# Create target with SMB credential (Windows hosts)
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_target>
    <name>Windows Domain Controllers</name>
    <hosts>192.168.1.20,192.168.1.21</hosts>
    <port_list id="33d0cd82-57c6-11e1-8ed1-406186ea4fc5"/>
    <smb_credential id="SMB_CREDENTIAL_UUID_HERE"/>
    <alive_test>ICMP, TCP-ACK Service and ARP Ping</alive_test>
  </create_target>'

Scan Configuration

Built-in Scan Configs

Config Name OID Use Case
Full and fast daba56c8-73ec-11df-a475-002264764cea Standard production scan
Full and deep 708f25c4-7489-11df-8094-002264764cea Thorough scan, may be disruptive
System Discovery 8715c877-47a0-438d-98a3-27c7a6ab2196 Host and service enumeration

Create Custom Scan Config for Authenticated Scan

# Clone "Full and fast" config and customize
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_config>
    <copy>daba56c8-73ec-11df-a475-002264764cea</copy>
    <name>Authenticated Full Scan</name>
  </create_config>'

Running the Scan

Create and Start Scan Task

# Create scan task
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_task>
    <name>Weekly Authenticated Scan - Linux Prod</name>
    <config id="CONFIG_UUID"/>
    <target id="TARGET_UUID"/>
    <scanner id="08b69003-5fc2-4037-a479-93b440211c73"/>
  </create_task>'
 
# Start the scan task
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<start_task task_id="TASK_UUID"/>'
 
# Check scan progress
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<get_tasks task_id="TASK_UUID"/>'

Schedule Recurring Scans

# Create weekly schedule (every Sunday at 2:00 AM UTC)
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<create_schedule>
    <name>Weekly Sunday 2AM</name>
    <icalendar>
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTART:20240101T020000Z
RRULE:FREQ=WEEKLY;BYDAY=SU
DURATION:PT12H
END:VEVENT
END:VCALENDAR
    </icalendar>
    <timezone>UTC</timezone>
  </create_schedule>'

Exporting Results

# Export scan report as XML
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<get_reports report_id="REPORT_UUID" format_id="a994b278-1f62-11e1-96ac-406186ea4fc5"/>'
 
# Export as CSV
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<get_reports report_id="REPORT_UUID" format_id="c1645568-627a-11e3-a660-406186ea4fc5"/>'
 
# Use python-gvm for programmatic access
python3 -c "
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeCheckCommandTransform
 
connection = UnixSocketConnection(path='/run/gvmd/gvmd.sock')
transform = EtreeCheckCommandTransform()
with Gmp(connection=connection, transform=transform) as gmp:
    gmp.authenticate('admin', 'password')
    reports = gmp.get_reports()
    print(f'Total reports: {len(reports)}')
"

Validating Authentication Success

# Check if credentials were accepted during scan
# In the scan report, look for NVT "Authentication tests" results:
# - OID 1.3.6.1.4.1.25623.1.0.103591 (SSH authentication successful)
# - OID 1.3.6.1.4.1.25623.1.0.90023 (SMB authentication successful)
 
# Verify via gvm-cli
gvm-cli socket --socketpath /run/gvmd/gvmd.sock --gmp-username admin --gmp-password <password> --xml \
  '<get_results filter="name=SSH rows=10 sort-reverse=severity"/>'

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md2.2 KB

OpenVAS Authenticated Scan — API Reference

Libraries

Library Install Purpose
python-gvm pip install python-gvm GVM protocol client (GMP)

python-gvm Connection

from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeTransform
 
connection = UnixSocketConnection(path="/run/gvmd/gvmd.sock")
with Gmp(connection=connection, transform=EtreeTransform()) as gmp:
    gmp.authenticate("admin", "password")

Key GMP Methods

Method Description
get_scan_configs() List scan configuration profiles
get_credentials() List stored credentials
create_credential(name=, type=, login=, password=) Create scan credential
create_target(name=, hosts=, ssh_credential_id=) Create scan target with creds
create_task(name=, config_id=, target_id=, scanner_id=) Create scan task
start_task(task_id) Start a scan task
get_task(task_id) Get task status and progress
get_report(report_id, filter_string=) Fetch scan results

Scan Configuration IDs

Name ID Description
Full and fast daba56c8-73ec-11df-a475-002264764cea Default comprehensive scan
Full and deep 708f25c4-7489-11df-8094-002264764cea Thorough but slower scan
Discovery 8715c877-47a0-438d-98a3-27c7a6ab2196 Network discovery only

Credential Types

Type Protocol Default Port
USERNAME_PASSWORD (SSH) SSH 22
USERNAME_PASSWORD (SMB) SMB/WMI 445
USERNAME_PASSWORD (ESXi) VMware 443
SNMP SNMP 161

OpenVAS CLI (ospd-openvas)

gvm-cli socket --socketpath /run/gvmd/gvmd.sock --xml "<get_version/>"
greenbone-feed-sync --type SCAP     # Sync vulnerability data
greenbone-feed-sync --type CERT     # Sync CERT advisories
greenbone-feed-sync --type GVMD_DATA  # Sync scan configs

External References

standards.md2.9 KB

Standards and References - Authenticated Scanning with OpenVAS

Primary Standards

NIST SP 800-115

NIST SP 800-53 Rev 5 - RA-5

CIS Controls v8 - Control 7

  • Title: Continuous Vulnerability Management
  • URL: https://www.cisecurity.org/controls/continuous-vulnerability-management
  • Sub-controls:
    • 7.1: Establish and maintain a vulnerability management process
    • 7.4: Perform authenticated vulnerability scanning with agents or credentialed scans
    • 7.5: Perform automated vulnerability scans of internal enterprise assets on a quarterly basis

PCI DSS v4.0 - Requirement 11.3

  • Title: External and Internal Vulnerabilities Are Regularly Identified, Prioritized, and Addressed
  • Requirement: Internal vulnerability scans must be performed at least quarterly and after any significant change; authenticated scanning is required for comprehensive assessment

OpenVAS/GVM Technical References

Greenbone Community Edition

GVM Architecture

  • Scanner: openvas-scanner performs the actual vulnerability tests
  • Manager: gvmd manages scan tasks, credentials, targets, and results
  • Web Interface: Greenbone Security Assistant (GSA) provides browser-based management
  • Database: PostgreSQL stores configurations and results
  • Cache: Redis provides high-speed NVT metadata caching

python-gvm Library

GMP Protocol

Compliance Mapping

Framework Control Authenticated Scan Requirement
NIST 800-53 RA-5 Credentialed scanning for host-level assessment
PCI DSS 4.0 11.3.1 Internal vulnerability scanning quarterly
CIS Controls v8 7.4 Authenticated vulnerability scanning
ISO 27001 A.8.8 Technical vulnerability management
HIPAA 164.312(a)(1) Technical safeguards evaluation
SOC 2 CC7.1 Vulnerability identification and remediation
workflows.md3.1 KB

Workflows - Authenticated Scanning with OpenVAS

Workflow 1: Initial Authenticated Scan Setup

Steps

  1. Install and initialize GVM

    • Install GVM packages or deploy Docker containers
    • Run gvm-setup to initialize database and create admin account
    • Verify all services with gvm-check-setup
  2. Synchronize vulnerability feeds

    • Run greenbone-feed-sync for NVT, SCAP, and CERT data
    • Wait for initial sync to complete (15-30 minutes)
    • Verify feed status in GSA dashboard
  3. Create scan credentials

    • Create SSH key pair for Linux scanning: ssh-keygen -t ed25519 -f scan_key
    • Deploy public key to target hosts: ssh-copy-id -i scan_key.pub scan_user@target
    • Create Windows service account with local admin rights for SMB scanning
    • Import credentials into GVM via GSA or gvm-cli
  4. Define scan targets

    • Group hosts by OS type and credential type
    • Assign appropriate credentials to each target group
    • Configure alive test method (ICMP + TCP-ACK recommended)
  5. Select scan configuration

    • Use "Full and fast" for production environments
    • Use "Full and deep" for pre-production/staging
    • Clone and customize for specific compliance requirements
  6. Execute initial scan

    • Create scan task linking target, config, and schedule
    • Run scan during maintenance window for first execution
    • Monitor progress through GSA dashboard
  7. Validate authentication success

    • Check report for authentication NVT results
    • Verify SSH/SMB login success indicators
    • Compare finding count against unauthenticated baseline

Workflow 2: Recurring Authenticated Scan

Trigger

Weekly schedule (Sunday 2:00 AM UTC).

Steps

  1. GVM automatically starts scheduled scan task
  2. Scanner performs alive detection on all target hosts
  3. For each responding host:
    • Authenticate using stored credentials
    • Run all applicable NVT checks
    • Collect installed package lists, registry keys, configurations
  4. Results stored in PostgreSQL database
  5. Compare against previous scan for delta analysis
  6. Generate report in XML/CSV/PDF format
  7. Export results to vulnerability management platform (DefectDojo, Jira)

Workflow 3: Scan Result Export Pipeline

Steps

  1. Scan completes and report is generated
  2. Python script fetches report via GMP protocol
  3. Parse XML results and extract:
    • CVE identifiers
    • CVSS scores
    • Affected hosts and ports
    • NVT descriptions and remediation guidance
  4. Transform into standardized format
  5. Upload to DefectDojo via reimport API
  6. Create Jira tickets for Critical/High findings
  7. Update vulnerability SLA tracking database

Workflow 4: Credential Rotation

Trigger

Monthly or upon security policy requirement.

Steps

  1. Generate new SSH key pair or update service account password
  2. Deploy new credentials to target hosts via configuration management (Ansible, Puppet)
  3. Update credential objects in GVM
  4. Run validation scan on subset of targets
  5. Verify authentication success in validation report
  6. If successful, update production scan tasks
  7. Revoke old credentials from target hosts

Scripts 2

agent.py7.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/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()
process.py9.5 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""OpenVAS Authenticated Scan Automation.

Manages scan targets, credentials, tasks, and result export using
the Greenbone Management Protocol (GMP) via python-gvm.
"""

import argparse
import csv
import json
import sys
import xml.etree.ElementTree as ET
from datetime import datetime, timezone
from pathlib import Path

try:
    from gvm.connections import UnixSocketConnection
    from gvm.protocols.gmp import Gmp
    from gvm.transforms import EtreeCheckCommandTransform
except ImportError:
    print("Install python-gvm: pip install python-gvm")
    sys.exit(1)

DEFAULT_SOCKET = "/run/gvmd/gvmd.sock"
FULL_AND_FAST_CONFIG = "daba56c8-73ec-11df-a475-002264764cea"
ALL_IANA_PORTS = "33d0cd82-57c6-11e1-8ed1-406186ea4fc5"
OPENVAS_SCANNER = "08b69003-5fc2-4037-a479-93b440211c73"


def connect_gmp(socket_path, username, password):
    """Establish authenticated GMP connection."""
    connection = UnixSocketConnection(path=socket_path)
    transform = EtreeCheckCommandTransform()
    gmp = Gmp(connection=connection, transform=transform)
    gmp.authenticate(username, password)
    return gmp


def create_ssh_credential(gmp, name, login, key_path=None, password=None):
    """Create SSH credential for Linux authenticated scanning."""
    if key_path:
        with open(key_path, "r") as f:
            private_key = f.read()
        credential = gmp.create_credential(
            name=name,
            credential_type=gmp.types.CredentialType.USERNAME_SSH_KEY,
            login=login,
            key_phrase=password or "",
            private_key=private_key,
        )
    else:
        credential = gmp.create_credential(
            name=name,
            credential_type=gmp.types.CredentialType.USERNAME_PASSWORD,
            login=login,
            password=password,
        )
    cred_id = credential.get("id")
    print(f"[+] Created SSH credential: {name} (ID: {cred_id})")
    return cred_id


def create_smb_credential(gmp, name, login, password):
    """Create SMB credential for Windows authenticated scanning."""
    credential = gmp.create_credential(
        name=name,
        credential_type=gmp.types.CredentialType.USERNAME_PASSWORD,
        login=login,
        password=password,
    )
    cred_id = credential.get("id")
    print(f"[+] Created SMB credential: {name} (ID: {cred_id})")
    return cred_id


def create_target(gmp, name, hosts, ssh_cred_id=None, smb_cred_id=None, ssh_port=22):
    """Create scan target with associated credentials."""
    kwargs = {
        "name": name,
        "hosts": hosts if isinstance(hosts, list) else [hosts],
        "port_list_id": ALL_IANA_PORTS,
        "alive_test": gmp.types.AliveTest.ICMP_TCP_ACK_SERVICE_AND_ARP_PING,
    }
    if ssh_cred_id:
        kwargs["ssh_credential_id"] = ssh_cred_id
        kwargs["ssh_credential_port"] = ssh_port
    if smb_cred_id:
        kwargs["smb_credential_id"] = smb_cred_id

    target = gmp.create_target(**kwargs)
    target_id = target.get("id")
    print(f"[+] Created target: {name} (ID: {target_id})")
    return target_id


def create_scan_task(gmp, name, target_id, config_id=FULL_AND_FAST_CONFIG, schedule_id=None):
    """Create scan task with target and configuration."""
    kwargs = {
        "name": name,
        "config_id": config_id,
        "target_id": target_id,
        "scanner_id": OPENVAS_SCANNER,
    }
    if schedule_id:
        kwargs["schedule_id"] = schedule_id

    task = gmp.create_task(**kwargs)
    task_id = task.get("id")
    print(f"[+] Created task: {name} (ID: {task_id})")
    return task_id


def start_scan(gmp, task_id):
    """Start a scan task and return report ID."""
    response = gmp.start_task(task_id)
    report_id = response.find("report_id").text
    print(f"[+] Scan started. Report ID: {report_id}")
    return report_id


def get_task_status(gmp, task_id):
    """Check scan task progress."""
    task = gmp.get_task(task_id)
    status = task.find("task/status").text
    progress = task.find("task/progress")
    progress_pct = progress.text if progress is not None else "N/A"
    return {"status": status, "progress": progress_pct}


def export_report_csv(gmp, report_id, output_path):
    """Export scan report results to CSV."""
    report = gmp.get_report(
        report_id=report_id,
        report_format_id="c1645568-627a-11e3-a660-406186ea4fc5",
        ignore_pagination=True,
        details=True,
    )
    results = []
    for result in report.iter("result"):
        nvt = result.find("nvt")
        if nvt is None:
            continue
        host = result.find("host")
        port = result.find("port")
        severity = result.find("severity")
        cve_refs = nvt.find("cve")
        results.append({
            "host": host.text if host is not None else "",
            "port": port.text if port is not None else "",
            "nvt_name": nvt.findtext("name", ""),
            "nvt_oid": nvt.get("oid", ""),
            "severity": severity.text if severity is not None else "",
            "cve": cve_refs.text if cve_refs is not None else "",
            "description": result.findtext("description", "")[:500],
        })

    with open(output_path, "w", newline="", encoding="utf-8") as f:
        if results:
            writer = csv.DictWriter(f, fieldnames=results[0].keys())
            writer.writeheader()
            writer.writerows(results)

    print(f"[+] Exported {len(results)} findings to {output_path}")
    return results


def check_auth_success(gmp, report_id):
    """Verify authentication was successful during scan."""
    report = gmp.get_report(report_id=report_id, ignore_pagination=True, details=True)
    auth_results = {
        "ssh_success": [],
        "ssh_failed": [],
        "smb_success": [],
        "smb_failed": [],
    }
    for result in report.iter("result"):
        nvt = result.find("nvt")
        if nvt is None:
            continue
        oid = nvt.get("oid", "")
        host = result.findtext("host", "")
        description = result.findtext("description", "")

        if oid == "1.3.6.1.4.1.25623.1.0.103591":
            if "successful" in description.lower():
                auth_results["ssh_success"].append(host)
            else:
                auth_results["ssh_failed"].append(host)
        elif oid == "1.3.6.1.4.1.25623.1.0.90023":
            if "successful" in description.lower():
                auth_results["smb_success"].append(host)
            else:
                auth_results["smb_failed"].append(host)

    print("[*] Authentication Results:")
    print(f"    SSH Success: {len(auth_results['ssh_success'])} hosts")
    print(f"    SSH Failed: {len(auth_results['ssh_failed'])} hosts")
    print(f"    SMB Success: {len(auth_results['smb_success'])} hosts")
    print(f"    SMB Failed: {len(auth_results['smb_failed'])} hosts")
    return auth_results


def main():
    parser = argparse.ArgumentParser(description="OpenVAS Authenticated Scan Automation")
    parser.add_argument("--socket", default=DEFAULT_SOCKET, help="GVM socket path")
    parser.add_argument("--username", default="admin", help="GVM username")
    parser.add_argument("--password", required=True, help="GVM password")

    sub = parser.add_subparsers(dest="command")

    cred_parser = sub.add_parser("create-credential", help="Create scan credential")
    cred_parser.add_argument("--name", required=True)
    cred_parser.add_argument("--type", choices=["ssh", "smb"], required=True)
    cred_parser.add_argument("--login", required=True)
    cred_parser.add_argument("--cred-password")
    cred_parser.add_argument("--key-path")

    target_parser = sub.add_parser("create-target", help="Create scan target")
    target_parser.add_argument("--name", required=True)
    target_parser.add_argument("--hosts", required=True, help="Comma-separated hosts")
    target_parser.add_argument("--ssh-cred-id")
    target_parser.add_argument("--smb-cred-id")

    scan_parser = sub.add_parser("start-scan", help="Create and start scan")
    scan_parser.add_argument("--name", required=True)
    scan_parser.add_argument("--target-id", required=True)

    export_parser = sub.add_parser("export", help="Export scan report")
    export_parser.add_argument("--report-id", required=True)
    export_parser.add_argument("--output", default="openvas_results.csv")

    status_parser = sub.add_parser("status", help="Check scan task status")
    status_parser.add_argument("--task-id", required=True)

    auth_parser = sub.add_parser("check-auth", help="Verify authentication success")
    auth_parser.add_argument("--report-id", required=True)

    args = parser.parse_args()

    gmp = connect_gmp(args.socket, args.username, args.password)

    if args.command == "create-credential":
        if args.type == "ssh":
            create_ssh_credential(gmp, args.name, args.login, args.key_path, args.cred_password)
        else:
            create_smb_credential(gmp, args.name, args.login, args.cred_password)
    elif args.command == "create-target":
        hosts = args.hosts.split(",")
        create_target(gmp, args.name, hosts, args.ssh_cred_id, args.smb_cred_id)
    elif args.command == "start-scan":
        task_id = create_scan_task(gmp, args.name, args.target_id)
        start_scan(gmp, task_id)
    elif args.command == "export":
        export_report_csv(gmp, args.report_id, args.output)
    elif args.command == "status":
        status = get_task_status(gmp, args.task_id)
        print(f"Status: {status['status']}, Progress: {status['progress']}%")
    elif args.command == "check-auth":
        check_auth_success(gmp, args.report_id)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 2.3 KB
Keep exploring