Sécurité

Scanner les vulnérabilités avec OpenVAS et automatiser les rapports

15 janvier 2026

12 min de lecture

Contexte : OpenVAS = Greenbone Community Edition

OpenVAS (Open Vulnerability Assessment System) est un scanner de vulnérabilités open source, maintenant intégré à Greenbone Community Edition (GCE) depuis 2022. Il détecte les failles de sécurité, misconfigurations et services vulnérables sur votre infrastructure.

Greenbone propose deux versions :

  • Community Edition (GCE) : gratuite, feeds mis à jour quotidiennement
  • Enterprise : support commercial, authentification avancée, scalabilité

Pour les besoins critiques, GCE suffit largement. C'est la base du scanner le plus fiable du marché (benchmarked contre Nessus, Qualys).

Architecture : GVM (Greenbone Vulnerability Management)

L'écosystème Greenbone repose sur quatre composants principaux :

  • openvas-scanner : moteur de scan bas-niveau, exécute les tests de vulnérabilités (NVT = Network Vulnerability Tests)
  • gvmd (Greenbone Vulnerability Manager Daemon) : gère la logique métier (targets, tasks, rapports, permissions)
  • gsad (Greenbone Security Assistant Daemon) : interface web (JavaScript/React)
  • ospd-openvas : bridge entre scanner OpenVAS et gvmd via le protocole OSP (Open Scanner Protocol)

Tous ces composants tournent en arrière-plan. Vous n'interagissez que via :

  • L'interface web gsad (port 443)
  • L'API GMP (Greenbone Management Protocol) sur socket Unix ou TCP

Les feeds (bases de vulnérabilités) sont :

  • NVT (Network Vulnerability Tests) : ~50 000 tests de sécurité
  • SCAP (Security Content Automation Protocol) : bases CVE/CPE officielles
  • CERT Advisories : alertes de sécurité

Installation : Docker Compose (recommandé)

Docker Compose est la méthode la plus simple pour déployer la stack GVM complète.

docker-compose.yml :

version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: gvmd
      POSTGRES_USER: gvmd
      POSTGRES_PASSWORD: gvmd_secure_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - gvm_network

  openvas-scanner:
    image: greenbone/openvas:2024.11
    depends_on:
      - postgres
    ports:
      - '9392:9392'
    volumes:
      - openvas_data:/var/lib/openvas
    environment:
      POSTGRES_DB: gvmd
      POSTGRES_USER: gvmd
      POSTGRES_PASSWORD: gvmd_secure_password
    networks:
      - gvm_network

  gvmd:
    image: greenbone/gvmd:2024.11
    depends_on:
      - postgres
      - openvas-scanner
    ports:
      - '9392:9392'
    volumes:
      - gvmd_data:/var/lib/gvm
    environment:
      POSTGRES_DB: gvmd
      POSTGRES_USER: gvmd
      POSTGRES_PASSWORD: gvmd_secure_password
      OPENVAS_SOCKET: /run/openvas/openvas.sock
    networks:
      - gvm_network

  gsad:
    image: greenbone/gsad:2024.11
    depends_on:
      - gvmd
    ports:
      - '443:443'
      - '80:80'
    environment:
      GVMD_SOCKET: /run/gvmd/gvmd.sock
    networks:
      - gvm_network

  greenbone-feed-sync:
    image: greenbone/greenbone-feed-sync:2024.11
    depends_on:
      - gvmd
    volumes:
      - gvmd_data:/var/lib/gvm
    environment:
      POSTGRES_DB: gvmd
      POSTGRES_USER: gvmd
      POSTGRES_PASSWORD: gvmd_secure_password
    networks:
      - gvm_network

volumes:
  postgres_data:
  openvas_data:
  gvmd_data:

networks:
  gvm_network:
    driver: bridge

Déploiement :

docker-compose up -d

# Attendre ~2-3 min que les services se stabilisent
sleep 180

# Vérifier que tout tourne
docker-compose ps

# Logs en temps réel
docker-compose logs -f gsad

# Accès : https://localhost
# Identifiants par défaut générés automatiquement (voir logs gvmd)

Après le premier démarrage, récupérez les identifiants admin dans les logs :

docker-compose logs gvmd | grep -i "admin\|password"

Installation native (Ubuntu 22.04+) :

# Ajouter le repo Greenbone
curl -sSf https://apt.greenbone.net/greenbone-apt-keyring.asc | sudo apt-key add -
echo "deb https://apt.greenbone.net/release focal main" | sudo tee /etc/apt/sources.list.d/greenbone.list

# Installer
sudo apt update
sudo apt install greenbone-community-openvas greenbone-community-gvmd greenbone-community-gsad

# Démarrer les services
sudo systemctl start openvas openvas-manager openvas-gsad
sudo systemctl enable openvas openvas-manager openvas-gsad

# Vérifier le port 443
sudo ss -tulpn | grep 443

Mise à jour des feeds de vulnérabilités

Les feeds (bases de vuln) doivent être à jour avant de lancer des scans sérieux. C'est critique.

Vérifier le statut des feeds :

docker-compose exec gvmd gvmd --help | grep -i feed

# Ou via l'API GMP
gvm-cli --gmp-username admin --gmp-password YOUR_PASSWORD socket \
  --xml '<get_nvt_families/>'

Forcer la mise à jour (Docker Compose) :

# Feeds NVT + SCAP + CERT
docker-compose exec greenbone-feed-sync greenbone-feed-sync

# Ou manuellement pour NVT uniquement
docker-compose exec greenbone-feed-sync greenbone-feed-sync --nvt

Vérifier que les feeds sont à jour :

# Lancer ceci dans l'interface web :
# Admin → NVT Families → devrait afficher ~50 000 NVT

Automatiser la mise à jour (optionnel) :

Ajouter un cron (machine hôte) pour synchroniser chaque nuit :

# /etc/cron.d/greenbone-feed-sync
0 2 * * * root docker-compose -f /path/to/docker-compose.yml exec greenbone-feed-sync greenbone-feed-sync >> /var/log/greenbone-sync.log 2>&1

Scan Profiles (Profils de scan)

Greenbone propose plusieurs profils pré-configurés selon votre besoin :

ProfilTempsCouvertureUsage
Discovery5-10 minDétection des servicesReconnaissance initiale
Full and fast30-60 min95% vulnérabilitésScans hebdo standard
Full and deep2-4 h99% vulnérabilitésAudits critiques
Full and very deep8-12 h100% couvertureAudits de conformité annuels

Récupérer l'ID des profils :

gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml '<get_configs/>'

# Vous verrez :
# Full and fast: daba56c8-73ec-11df-a475-002264764cea
# Full and deep: 708b0dae-2f51-45e8-9ecd-53a7f637b2f3

Configuration du premier scan

Étape 1 : Créer une cible

gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml '<create_target>
    <name>Production Servers</name>
    <hosts>192.168.1.0/24</hosts>
    <allow_simultaneous_ips>1</allow_simultaneous_ips>
  </create_target>'

# Réponse (noter le TARGET_ID)
# <create_target_response id="a123b456-c789..."/>

Étape 2 : Lancer un scan (Full and fast)

TARGET_ID="a123b456-c789..."
SCANNER_ID="08b69003-5fc2-4037-a479-93b440211c73"  # OpenVAS Default
CONFIG_ID="daba56c8-73ec-11df-a475-002264764cea"   # Full and fast

gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml "<create_task>
    <name>Weekly Prod Scan</name>
    <target id='$TARGET_ID'/>
    <config id='$CONFIG_ID'/>
    <scanner id='$SCANNER_ID'/>
    <preferences>
      <preference>
        <name>Timeout</name>
        <value>300</value>
      </preference>
    </preferences>
  </create_task>"

# Réponse (noter le TASK_ID)
# <create_task_response id="b234c567-d890..."/>

Étape 3 : Démarrer le scan

TASK_ID="b234c567-d890..."

gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml "<start_task task_id='$TASK_ID'/>"

Étape 4 : Monitorer la progression

TASK_ID="b234c567-d890..."

# Vérifier le statut en temps réel
watch -n 10 "gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml '<get_tasks task_id=\"$TASK_ID\" details=\"1\"/>' | grep -i 'Status\|Progress'"

Alternative : via l'interface web :

  1. Accédez à https://localhost
  2. Menu ScansTasksNew Task
  3. Remplissez : Nom, Target, Scan Config (Full and fast), Scanner
  4. Cliquez Create Task → bouton Start Task

Automatisation : scans programmés

Approche 1 : Scheduler Greenbone (GUI)

Dans l'interface web : ScansTasks → éditer une task → Schedule

Paramètres :

  • Fréquence : Hebdo, Mensuel, Personnalisé
  • Heure : 2 AM (off-hours recommandé)
  • Rappels d'alerte avant/après
Approche 2 : Script Python avec GMP

Installer le SDK Python :

pip install greenbone-feed-sync python-gvm

Script : scan_weekly.py

#!/usr/bin/env python3
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeTransform
import logging
from datetime import datetime

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

connection = UnixSocketConnection()
transform = EtreeTransform()

CONFIG_ID = 'daba56c8-73ec-11df-a475-002264764cea'  # Full and fast
SCANNER_ID = '08b69003-5fc2-4037-a479-93b440211c73'

with Gmp(connection, transform=transform) as gmp:
    gmp.authenticate('admin', 'YOUR_PASSWORD')

    # Créer ou récupérer cible
    target = gmp.create_target(
        name='Production-Weekly-Scan',
        hosts=['10.0.0.0/8'],
        allow_simultaneous_ips=True
    )
    target_id = target.get('id')
    logger.info(f"Target créée : {target_id}")

    # Créer task
    task = gmp.create_task(
        name=f'Weekly-Prod-Scan-{datetime.now().strftime("%Y%m%d")}',
        config_id=CONFIG_ID,
        target_id=target_id,
        scanner_id=SCANNER_ID
    )
    task_id = task.get('id')
    logger.info(f"Task créée : {task_id}")

    # Lancer
    gmp.start_task(task_id)
    logger.info(f"Scan démarré : {task_id}")

Lancer en cron :

# /etc/cron.d/greenbone-scan
0 2 * * 0 root /usr/bin/python3 /opt/scan_weekly.py >> /var/log/greenbone-scan.log 2>&1
Approche 3 : API REST pour CI/CD (GitLab/GitHub Actions)

GMP expose une API REST sur le port 9392 (avec authentification bearer token).

Exemple GitHub Actions :

name: Weekly Vulnerability Scan

on:
  schedule:
    - cron: '0 2 * * 0'  # Chaque dimanche 2 AM

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - name: Start Greenbone Scan
        run: |
          curl -X POST https://greenbone.internal:9392/api/tasks \
            -H "Authorization: Bearer ${{ secrets.GREENBONE_API_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "CI-CD-Weekly-Scan",
              "target_id": "YOUR_TARGET_ID",
              "config_id": "daba56c8-73ec-11df-a475-002264764cea"
            }'

      - name: Wait for scan completion (timeout: 4h)
        run: |
          timeout 14400 bash -c \
            'while [ $(curl -s https://greenbone.internal:9392/api/tasks/$TASK_ID \
              -H "Authorization: Bearer ${{ secrets.GREENBONE_API_TOKEN }}" \
              | jq -r .status) != "Done" ]; do sleep 30; done'

      - name: Download report as CSV
        run: |
          curl -o report.csv https://greenbone.internal:9392/api/reports/$REPORT_ID \
            -H "Authorization: Bearer ${{ secrets.GREENBONE_API_TOKEN }}"

      - name: Check for Critical vulnerabilities
        run: |
          CRITICAL_COUNT=$(awk -F',' '$10=="Critical" {count++} END {print count}' report.csv)
          if [ $CRITICAL_COUNT -gt 0 ]; then
            echo "FAILED: $CRITICAL_COUNT Critical vulnerabilities found"
            exit 1
          fi

Export et analyse des rapports

Récupérer le rapport après le scan

Une fois le scan terminé (statut Done), générez un rapport :

TASK_ID="b234c567-d890..."

# Récupérer le rapport le plus récent
gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml "<get_tasks task_id='$TASK_ID' details='1'/>" | grep '<report'

# La réponse contient <report id="..."/>

Formats d'export disponibles

FormatIDUsage
PDF (tables)c402cc3e-b531-11e1-9163-406186ea4fc5Rapports formels
CSVc1645568-627a-11e3-a660-406186ea4fc5Analyse Excel/Google Sheets
XMLa994b278-1f62-11e1-96ac-406186ea4fc5Intégration outils
JSON35ba7077-dc12-42f8-ab6d-2678ab61df24API/scripts

Exporter en PDF

REPORT_ID="c123d456-e789..."

gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml '<get_reports report_id="'$REPORT_ID'" format_id="c402cc3e-b531-11e1-9163-406186ea4fc5"/>' \
  | base64 -d > report.pdf

# Ouvrir
open report.pdf  # macOS
# ou xdg-open report.pdf  # Linux

Exporter en CSV (pour analyse)

gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml '<get_reports report_id="'$REPORT_ID'" format_id="c1645568-627a-11e3-a660-406186ea4fc5"/>' \
  | base64 -d > report.csv

Interpréter les résultats : CVSS et sévérité

OpenVAS utilise CVSS 3.1 pour scorer les vulnérabilités :

  • Critical (9.0-10.0) : Exploit trivial, impact maximal → Corriger en 24-48h
  • High (7.0-8.9) : Exploit probable, impact élevé → Corriger en 1 semaine
  • Medium (4.0-6.9) : Exploit possible → Corriger en 1 mois
  • Low (0.1-3.9) : Exploitation difficile → Corriger à la prochaine maintenance

Parser le CSV pour comptabiliser :

# Compter par sévérité
awk -F',' 'NR>1 {print $10}' report.csv | sort | uniq -c

# Résultat exemple :
# 12 Critical
# 45 High
# 87 Medium
# 156 Low

Bonnes pratiques de scanning

Réseau et timing
  • Scanner depuis un réseau dédié : les scans sont agressifs, peuvent saturer le réseau
  • Ne pas scanner en production sans accord écrit : risque d'indisponibilité
  • Planifier hors heures de pointe : scans Full and deep = 2-4h
  • Scans hebdo recommandés : minimum pour détecter les failles nouvelles
Gestion des résultats
  • Valider les faux positifs : ex. services détectés mais intentionnels
  • Créer des tickets d'audit : chaque Critical/High = ticket dans Jira/Azure DevOps
  • Prioriser par CVSS + Exploitabilité : un CVSS 7 exploitable en 2h > CVSS 8 sans PoC public
  • Baseline : 0 Critical : politique standard
  • SLA de correction : Critical = 48h, High = 1 semaine, Medium = 1 mois
Exclusions et optimisations
  • Whitelister les vulnérabilités connues/acceptées :
gvm-cli --gmp-username admin --gmp-password PASSWORD socket \
  --xml '<create_override>
    <nvt oid="1.3.6.1.4.1.25623.1.0.XXXXX"/>
    <text>AWS Security Group misconfiguration - expected</text>
  </create_override>'
  • Ajuster le timeout par service : bases de données lentes = augmenter timeout
  • Ne scanner que les ports ouverts : détecter avec Nmap d'abord
nmap -sS -p- 192.168.1.0/24 -oX ports.xml
# Importer ports.xml dans Greenbone comme target

Complétez OpenVAS avec audit CIS Benchmark pour la compliance, Wazuh pour la centralisation, et CrowdSec pour la protection proactive.

Alertes et notifications

Slack pour vulnérabilités critiques

Intégrez Slack pour être notifié immédiatement en cas de Critical/High trouvées.

Script : slack_notifier.py

#!/usr/bin/env python3
import requests
import csv
from pathlib import Path
import sys

SLACK_WEBHOOK = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

def send_slack_alert(severity, count, top_vulns):
    """Envoyer alerte Slack avec vulnérabilités"""

    color_map = {
        'Critical': '#dc2626',
        'High': '#f97316',
        'Medium': '#f59e0b',
        'Low': '#6b7280'
    }

    fields = [
        {
            "title": "Sévérité",
            "value": severity,
            "short": True
        },
        {
            "title": "Nombre",
            "value": str(count),
            "short": True
        }
    ]

    # Ajouter top 3 vulnérabilités
    for i, vuln in enumerate(top_vulns[:3], 1):
        fields.append({
            "title": f"#{i}",
            "value": f"{vuln['name'][:50]}... (CVSS {vuln['cvss']})",
            "short": False
        })

    payload = {
        "attachments": [{
            "color": color_map.get(severity, '#64748b'),
            "title": f"🚨 {count} {severity} Vulnerabilities Detected",
            "fields": fields,
            "footer": "Greenbone OpenVAS Scanner",
            "ts": int(__import__('time').time())
        }]
    }

    response = requests.post(SLACK_WEBHOOK, json=payload)
    return response.status_code == 200

def parse_csv_report(csv_path):
    """Parser le rapport CSV pour extraire sévérité et CVE"""
    vulns_by_severity = {}
    with open(csv_path) as f:
        reader = csv.DictReader(f)
        for row in reader:
            severity = row.get('Severity', 'Unknown')
            if severity not in vulns_by_severity:
                vulns_by_severity[severity] = []

            vulns_by_severity[severity].append({
                'name': row.get('Name', ''),
                'cvss': row.get('CVSS Score', 'N/A'),
                'cve': row.get('CVE', '')
            })

    return vulns_by_severity

if __name__ == '__main__':
    csv_path = sys.argv[1] if len(sys.argv) > 1 else 'report.csv'

    vulns = parse_csv_report(csv_path)

    # Envoyer alerte si Critical/High
    for severity in ['Critical', 'High']:
        if severity in vulns and len(vulns[severity]) > 0:
            send_slack_alert(severity, len(vulns[severity]), vulns[severity])
            print(f"✓ Alerte Slack envoyée pour {severity}")

Utiliser dans CI/CD :

# Après export du rapport CSV
python3 slack_notifier.py report.csv
Email automatique

Greenbone supporte nativement l'envoi d'email après scan.

Via l'interface web :

  1. Admin → Settings → Email Configuration
  2. Entrer SMTP (ex: Gmail avec App Password)
  3. Éditer une Task → Alerts → créer alerte Email

Script Python (alternative) :

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders

def send_report_email(recipient, csv_path, smtp_server='smtp.gmail.com', smtp_port=587):
    sender = "noreply@company.com"
    password = "YOUR_APP_PASSWORD"

    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = recipient
    msg['Subject'] = 'OpenVAS Weekly Scan Report'

    body = """
    Bonjour,

    Rapport de scan OpenVAS ci-joint.

    Action recommandée : corriger les Critical en priorité.

    Cordialement,
    Équipe Sécurité
    """

    msg.attach(MIMEText(body, 'plain'))

    # Attacher le CSV
    attachment = open(csv_path, 'rb')
    part = MIMEBase('application', 'octet-stream')
    part.set_payload(attachment.read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', f'attachment; filename= {Path(csv_path).name}')
    msg.attach(part)

    # Envoyer
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(sender, password)
        server.send_message(msg)

# Utiliser
send_report_email('security-team@company.com', 'report.csv')

Ressources et outils complémentaires

Outils connexes :

Prochaines étapes :

  1. Déployer Greenbone en production avec Docker Compose
  2. Importer vos targets (datacenters, infra cloud)
  3. Lancer un scan Full and deep pour baseline
  4. Exporter en CSV et prioriser les Critical
  5. Intégrer Slack/Email pour notifications automatiques
  6. Planifier scans hebdo via scheduler ou cron
  7. Documenter les whitelist de vulnérabilités connues/acceptées
Besoin d'aide sur ce sujet ?

Notre équipe d'experts est là pour vous accompagner dans vos projets d'infrastructure et d'infogérance.

Contactez-nous

Articles similaires