Comment analyser les résultats d'analyse Nmap au format XML

NmapNmapBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans le domaine de la cybersécurité, comprendre et analyser les résultats d'analyse de réseau est crucial pour maintenir une infrastructure sécurisée. Nmap (Network Mapper) est l'un des outils les plus utilisés pour la découverte de réseau et l'audit de sécurité. Ce tutoriel vous guidera à travers le processus d'interprétation des résultats d'analyse Nmap au format XML, vous dotant des compétences nécessaires pour exploiter cet outil puissant pour vos besoins en cybersécurité.

À la fin de ce labo, vous saurez comment exécuter des analyses Nmap avec une sortie XML, comprendre la structure des données XML, extraire des informations précieuses à l'aide d'outils en ligne de commande et de scripts Python, et identifier les problèmes de sécurité potentiels à partir des résultats de l'analyse.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL nmap(("Nmap")) -.-> nmap/NmapGroup(["Nmap"]) nmap/NmapGroup -.-> nmap/installation("Installation and Setup") nmap/NmapGroup -.-> nmap/common_ports("Common Ports Scanning") nmap/NmapGroup -.-> nmap/output_formats("Output Formats") nmap/NmapGroup -.-> nmap/save_output("Save Output to File") nmap/NmapGroup -.-> nmap/port_scanning("Port Scanning Methods") nmap/NmapGroup -.-> nmap/os_version_detection("OS and Version Detection") nmap/NmapGroup -.-> nmap/service_detection("Service Detection") subgraph Lab Skills nmap/installation -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} nmap/common_ports -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} nmap/output_formats -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} nmap/save_output -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} nmap/port_scanning -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} nmap/os_version_detection -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} nmap/service_detection -.-> lab-415516{{"Comment analyser les résultats d'analyse Nmap au format XML"}} end

Installation de Nmap et exécution d'une analyse XML de base

Qu'est-ce que Nmap ?

Nmap (Network Mapper) est un utilitaire gratuit et open source pour la découverte de réseau et l'audit de sécurité. Les professionnels de la sécurité du monde entier l'utilisent pour identifier les appareils qui fonctionnent sur leurs réseaux, découvrir les hôtes disponibles et les services qu'ils offrent, trouver les ports ouverts et détecter les vulnérabilités de sécurité.

Installation de Nmap

Commençons par installer Nmap sur notre système. Ouvrez une fenêtre de terminal et entrez les commandes suivantes :

sudo apt update
sudo apt install nmap -y

Une fois l'installation terminée, vérifiez que Nmap est correctement installé en vérifiant sa version :

nmap --version

Vous devriez voir une sortie similaire à ceci :

Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1f libssh2-1.8.0 libz-1.2.11 libpcre-8.39 nmap-libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

Exécution d'une analyse Nmap de base avec sortie XML

Nmap peut enregistrer ses résultats d'analyse au format XML, ce qui offre un moyen structuré d'analyser les données par programme. Exécutons une analyse de base de notre machine locale et enregistrons les résultats au format XML :

sudo nmap -A -T4 -oX ~/project/localhost_scan.xml localhost

Cette commande effectue :

  • -A : Active la détection du système d'exploitation (OS detection), la détection de version (version detection), l'analyse de script (script scanning) et le traceroute
  • -T4 : Définit le modèle de synchronisation sur "agressif"
  • -oX : Spécifie que la sortie doit être au format XML
  • localhost : La cible à analyser (notre propre machine)

L'analyse peut prendre une minute ou deux. Une fois terminé, vous verrez un résumé des résultats de l'analyse dans le terminal.

Affichage des résultats de l'analyse XML

Examinons le fichier XML que nous venons de créer :

cat ~/project/localhost_scan.xml

La sortie sera un document XML structuré contenant des informations détaillées sur l'analyse. Cela peut sembler accablant au début, mais nous apprendrons à l'interpréter dans les prochaines étapes.

Vérifions également la structure de base du fichier XML à l'aide de la commande head :

head -n 20 ~/project/localhost_scan.xml

Cela affiche les 20 premières lignes du fichier XML, ce qui nous donne un aperçu de sa structure.

Examen de la structure de sortie XML

Comprendre le format XML de Nmap

La sortie XML de Nmap suit une structure hiérarchique qui organise les informations d'analyse de manière logique. Explorons les principaux éléments de cette structure :

  1. <nmaprun> : L'élément racine qui contient toutes les informations d'analyse
  2. <scaninfo> : Détails sur le type d'analyse et les paramètres
  3. <host> : Informations sur chaque hôte analysé
    • <status> : Indique si l'hôte est actif (up) ou inactif (down)
    • <address> : Adresses IP et MAC
    • <hostnames> : Noms DNS
    • <ports> : Détails sur les ports analysés
      • <port> : Informations sur un port spécifique
        • <state> : Indique si le port est ouvert (open), fermé (closed) ou filtré (filtered)
        • <service> : Informations sur le service si disponibles
    • <os> : Résultats de la détection du système d'exploitation (Operating System detection)
    • <times> : Informations de synchronisation sur l'analyse

Utilisation d'outils en ligne de commande pour extraire des informations

Les fichiers XML peuvent être difficiles à lire dans leur forme brute. Utilisons quelques outils en ligne de commande pour extraire des informations spécifiques de nos résultats d'analyse.

Tout d'abord, comptons le nombre de ports ouverts qui ont été trouvés à l'aide de grep et wc :

grep -c "state=\"open\"" ~/project/localhost_scan.xml

Cette commande recherche les instances de state="open" dans le fichier XML et les compte.

Ensuite, identifions les ports ouverts et leurs services à l'aide de grep avec l'option -A pour afficher les lignes après la correspondance :

grep -A 3 "state=\"open\"" ~/project/localhost_scan.xml

Cela affichera chaque instance d'un port ouvert ainsi que les 3 lignes qui le suivent, qui incluent généralement des informations sur le service.

Nous pouvons également utiliser xmllint pour formater le fichier XML pour une meilleure lisibilité. Installons-le d'abord :

sudo apt install libxml2-utils -y

Maintenant, formatons le fichier XML :

xmllint --format ~/project/localhost_scan.xml > ~/project/formatted_scan.xml

Regardons le fichier formaté :

head -n 50 ~/project/formatted_scan.xml

Cela affiche les 50 premières lignes du fichier XML formaté, qui devraient être beaucoup plus faciles à lire.

Enfin, extrayons des informations spécifiques sur l'état de l'hôte à l'aide de xmllint avec XPath :

xmllint --xpath "//host/status/@state" ~/project/localhost_scan.xml

Cette commande utilise XPath pour extraire l'attribut d'état (state attribute) de tous les éléments d'état (status elements) sous les éléments hôtes (host elements).

Analyse du XML Nmap avec Python

Introduction à l'analyse XML avec Python

Python fournit des bibliothèques puissantes pour l'analyse des fichiers XML. Dans cette étape, nous allons créer un script Python simple pour analyser nos résultats d'analyse Nmap et les afficher dans un format plus lisible.

Création d'un analyseur XML de base

Créons un script Python qui utilise le module xml.etree.ElementTree pour analyser le fichier XML Nmap. Ce module est inclus dans la bibliothèque standard Python, nous n'avons donc rien à installer de plus.

Créez un nouveau fichier appelé parse_nmap.py dans le répertoire du projet :

nano ~/project/parse_nmap.py

Copiez et collez le code suivant dans l'éditeur :

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import sys

def parse_nmap_xml(xml_file):
    try:
        ## Parse the XML file
        tree = ET.parse(xml_file)
        root = tree.getroot()

        ## Print scan information
        print("Nmap Scan Report")
        print("=" * 50)
        print(f"Scan started at: {root.get('startstr')}")
        print(f"Nmap version: {root.get('version')}")
        print(f"Nmap command: {root.get('args')}")
        print("=" * 50)

        ## Process each host in the scan
        for host in root.findall('host'):
            ## Get host addresses
            for addr in host.findall('address'):
                if addr.get('addrtype') == 'ipv4':
                    ip_address = addr.get('addr')
                    print(f"\nHost: {ip_address}")

            ## Get hostname if available
            hostnames = host.find('hostnames')
            if hostnames is not None:
                for hostname in hostnames.findall('hostname'):
                    print(f"Hostname: {hostname.get('name')}")

            ## Get host status
            status = host.find('status')
            if status is not None:
                print(f"Status: {status.get('state')}")

            ## Process ports
            ports = host.find('ports')
            if ports is not None:
                print("\nOpen Ports:")
                print("-" * 50)
                print(f"{'PORT':<10}{'STATE':<10}{'SERVICE':<15}{'VERSION'}")
                print("-" * 50)

                for port in ports.findall('port'):
                    port_id = port.get('portid')
                    protocol = port.get('protocol')

                    ## Get port state
                    state = port.find('state')
                    port_state = state.get('state') if state is not None else "unknown"

                    ## Skip closed ports
                    if port_state != "open":
                        continue

                    ## Get service information
                    service = port.find('service')
                    if service is not None:
                        service_name = service.get('name', '')
                        service_product = service.get('product', '')
                        service_version = service.get('version', '')
                        service_info = f"{service_product} {service_version}".strip()
                    else:
                        service_name = ""
                        service_info = ""

                    print(f"{port_id}/{protocol:<5} {port_state:<10}{service_name:<15}{service_info}")

            ## Get OS detection information
            os = host.find('os')
            if os is not None:
                print("\nOS Detection:")
                for osmatch in os.findall('osmatch'):
                    print(f"OS: {osmatch.get('name')} (Accuracy: {osmatch.get('accuracy')}%)")

    except ET.ParseError as e:
        print(f"Error parsing XML file: {e}")
        return False
    except Exception as e:
        print(f"Error: {e}")
        return False

    return True

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <nmap_xml_file>")
        sys.exit(1)

    xml_file = sys.argv[1]
    if not parse_nmap_xml(xml_file):
        sys.exit(1)

Enregistrez le fichier en appuyant sur Ctrl+O, puis sur Enter, et quittez nano avec Ctrl+X.

Maintenant, rendez le script exécutable :

chmod +x ~/project/parse_nmap.py

Exécution de l'analyseur

Exécutons notre script Python sur le fichier XML Nmap que nous avons créé précédemment :

python ~/project/parse_nmap.py ~/project/localhost_scan.xml

Vous devriez voir une sortie bien formatée des résultats de l'analyse, comprenant :

  • Informations de base sur l'analyse
  • Détails de l'hôte
  • Ports et services ouverts
  • Résultats de la détection du système d'exploitation (OS detection) si disponibles

Cette sortie formatée est beaucoup plus facile à lire que le fichier XML brut et met en évidence les informations les plus importantes de l'analyse.

Comprendre le code de l'analyseur

Passons en revue ce que fait notre script Python :

  1. Il utilise xml.etree.ElementTree pour analyser le fichier XML
  2. Il extrait les informations générales sur l'analyse de l'élément racine (root element)
  3. Pour chaque hôte trouvé dans l'analyse :
    • Il extrait les adresses IP et les noms d'hôte (hostnames)
    • Il détermine si l'hôte est actif (up) ou inactif (down)
    • Il répertorie tous les ports ouverts, y compris le numéro de port, le protocole, le nom du service et la version
    • Il extrait les informations de détection du système d'exploitation (OS detection) si disponibles

Cette approche structurée nous permet de nous concentrer sur les informations les plus pertinentes tout en ignorant la complexité XML.

Extraction d'informations pertinentes pour la sécurité

Informations de sécurité issues des analyses Nmap

Maintenant que nous pouvons analyser les données XML Nmap, étendons notre script pour extraire des informations pertinentes pour la sécurité. Cela comprend :

  1. L'identification des ports ouverts potentiellement risqués
  2. La détection des versions de service obsolètes
  3. La synthèse des problèmes de sécurité

Créons une version améliorée de notre analyseur qui se concentre sur l'analyse de la sécurité.

Création d'un script d'analyse de la sécurité

Créez un nouveau fichier appelé security_analysis.py :

nano ~/project/security_analysis.py

Copiez et collez le code suivant :

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import sys
import datetime

## Define potentially risky ports
HIGH_RISK_PORTS = {
    '21': 'FTP - File Transfer Protocol (often unencrypted)',
    '23': 'Telnet - Unencrypted remote access',
    '25': 'SMTP - Email transfer (may allow relay)',
    '445': 'SMB - Windows file sharing (potential target for worms)',
    '3389': 'RDP - Remote Desktop Protocol (target for brute force)',
    '1433': 'MSSQL - Microsoft SQL Server',
    '3306': 'MySQL - Database access',
    '5432': 'PostgreSQL - Database access'
}

## Services with known security issues
OUTDATED_SERVICES = {
    'ssh': [
        {'version': '1', 'reason': 'SSHv1 has known vulnerabilities'},
        {'version': 'OpenSSH 7', 'reason': 'Older OpenSSH versions have multiple CVEs'}
    ],
    'http': [
        {'version': 'Apache httpd 2.2', 'reason': 'Apache 2.2.x is end-of-life'},
        {'version': 'Apache httpd 2.4.1', 'reason': 'Apache versions before 2.4.30 have known vulnerabilities'},
        {'version': 'nginx 1.14', 'reason': 'Older nginx versions have security issues'}
    ]
}

def analyze_security(xml_file):
    try:
        ## Parse the XML file
        tree = ET.parse(xml_file)
        root = tree.getroot()

        ## Prepare the report
        report = []
        report.append("NMAP SECURITY ANALYSIS REPORT")
        report.append("=" * 50)
        report.append(f"Report generated on: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        report.append(f"Scan started at: {root.get('startstr')}")
        report.append(f"Scan command: {root.get('args')}")
        report.append("=" * 50)

        ## Track security findings
        high_risk_services = []
        potentially_outdated = []
        exposed_services = []

        ## Process each host in the scan
        for host in root.findall('host'):
            ## Get host addresses
            ip_address = None
            for addr in host.findall('address'):
                if addr.get('addrtype') == 'ipv4':
                    ip_address = addr.get('addr')

            hostname = "Unknown"
            hostnames = host.find('hostnames')
            if hostnames is not None:
                hostname_elem = hostnames.find('hostname')
                if hostname_elem is not None:
                    hostname = hostname_elem.get('name')

            report.append(f"\nHOST: {ip_address} ({hostname})")
            report.append("-" * 50)

            ## Process ports
            ports = host.find('ports')
            if ports is None:
                report.append("No port information available")
                continue

            open_ports = 0
            for port in ports.findall('port'):
                port_id = port.get('portid')
                protocol = port.get('protocol')

                ## Get port state
                state = port.find('state')
                if state is None or state.get('state') != "open":
                    continue

                open_ports += 1

                ## Get service information
                service = port.find('service')
                if service is None:
                    service_name = "unknown"
                    service_product = ""
                    service_version = ""
                else:
                    service_name = service.get('name', 'unknown')
                    service_product = service.get('product', '')
                    service_version = service.get('version', '')

                service_full = f"{service_product} {service_version}".strip()

                ## Check if this is a high-risk port
                if port_id in HIGH_RISK_PORTS:
                    high_risk_services.append(f"{ip_address}:{port_id} ({service_name}) - {HIGH_RISK_PORTS[port_id]}")

                ## Check for outdated services
                if service_name in OUTDATED_SERVICES:
                    for outdated in OUTDATED_SERVICES[service_name]:
                        if outdated['version'] in service_full:
                            potentially_outdated.append(f"{ip_address}:{port_id} - {service_name} {service_full} - {outdated['reason']}")

                ## Track all exposed services
                exposed_services.append(f"{ip_address}:{port_id}/{protocol} - {service_name} {service_full}")

            report.append(f"Open ports: {open_ports}")

        ## Add security findings to report
        report.append("\nSECURITY FINDINGS")
        report.append("=" * 50)

        ## High-risk services
        report.append("\nHIGH-RISK SERVICES")
        report.append("-" * 50)
        if high_risk_services:
            for service in high_risk_services:
                report.append(service)
        else:
            report.append("No high-risk services detected")

        ## Potentially outdated services
        report.append("\nPOTENTIALLY OUTDATED SERVICES")
        report.append("-" * 50)
        if potentially_outdated:
            for service in potentially_outdated:
                report.append(service)
        else:
            report.append("No potentially outdated services detected")

        ## Exposed services inventory
        report.append("\nEXPOSED SERVICES INVENTORY")
        report.append("-" * 50)
        if exposed_services:
            for service in exposed_services:
                report.append(service)
        else:
            report.append("No exposed services detected")

        ## Write the report to a file
        report_file = "security_report.txt"
        with open(report_file, 'w') as f:
            f.write('\n'.join(report))

        print(f"Security analysis complete. Report saved to {report_file}")

        ## Display a summary
        print("\nSummary:")
        print(f"- High-risk services: {len(high_risk_services)}")
        print(f"- Potentially outdated services: {len(potentially_outdated)}")
        print(f"- Total exposed services: {len(exposed_services)}")

    except ET.ParseError as e:
        print(f"Error parsing XML file: {e}")
        return False
    except Exception as e:
        print(f"Error: {e}")
        return False

    return True

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <nmap_xml_file>")
        sys.exit(1)

    xml_file = sys.argv[1]
    if not analyze_security(xml_file):
        sys.exit(1)

Enregistrez le fichier en appuyant sur Ctrl+O, puis sur Enter, et quittez nano avec Ctrl+X.

Rendez le script exécutable :

chmod +x ~/project/security_analysis.py

Exécution de l'analyse de la sécurité

Exécutons notre script d'analyse de la sécurité sur le fichier XML Nmap :

cd ~/project
./security_analysis.py localhost_scan.xml

Le script analysera les résultats de l'analyse et générera un rapport de sécurité axé sur les vulnérabilités potentielles, en l'enregistrant dans un fichier appelé security_report.txt.

Regardons le contenu du rapport :

cat ~/project/security_report.txt

Comprendre l'analyse de la sécurité

Le script d'analyse de la sécurité remplit plusieurs fonctions importantes :

  1. Identification des ports à haut risque (High-Risk Port Identification) : Il identifie les ports couramment exploités comme FTP (21), Telnet (23) et RDP (3389), qui sont des cibles fréquentes pour les attaquants.

  2. Détection des services obsolètes (Outdated Service Detection) : Il recherche les anciennes versions de services comme SSH, Apache et nginx qui peuvent présenter des vulnérabilités de sécurité connues.

  3. Inventaire des services exposés (Exposed Services Inventory) : Il crée un inventaire complet de tous les ports et services ouverts, ce qui est précieux pour l'audit de sécurité.

  4. Catégorisation des risques (Risk Categorization) : Il organise les résultats par niveau de risque pour aider à hiérarchiser les améliorations de la sécurité.

Ce type d'analyse est essentiel pour que les professionnels de la sécurité identifient les vulnérabilités potentielles d'un réseau avant que les attaquants ne puissent les exploiter.

Extension de l'analyse

Dans un scénario réel, vous pouvez étendre cette analyse en :

  1. Ajoutant davantage de ports à haut risque à la liste de détection
  2. Mettant à jour les définitions de service obsolètes avec les dernières informations sur les vulnérabilités
  3. Intégrant des bases de données de vulnérabilités pour rechercher les CVE (Common Vulnerabilities and Exposures) connues
  4. Ajoutant des recommandations pour la correction des problèmes détectés

La capacité d'analyser par programmation les données XML Nmap est une compétence puissante pour les professionnels de la cybersécurité, car elle permet une évaluation automatisée des vulnérabilités et une intégration avec des systèmes de surveillance de la sécurité plus vastes.

Résumé

Félicitations pour avoir terminé ce labo sur l'analyse des résultats d'analyse Nmap au format XML. Vous avez acquis plusieurs compétences importantes :

  1. Installation et exécution de Nmap (Installing and Running Nmap) : Vous avez appris à installer Nmap et à exécuter des analyses avec une sortie XML, ce qui constitue une base pour la reconnaissance du réseau.

  2. Compréhension de la structure XML (Understanding XML Structure) : Vous avez exploré la structure des fichiers XML Nmap et utilisé des outils de ligne de commande pour extraire des informations spécifiques, ce qui vous donne la possibilité d'analyser rapidement les résultats de l'analyse.

  3. Analyse XML avec Python (Parsing XML with Python) : Vous avez créé un script Python pour analyser et afficher les résultats d'analyse Nmap dans un format lisible, démontrant ainsi comment travailler par programmation avec des données structurées.

  4. Analyse de la sécurité (Security Analysis) : Vous avez étendu vos compétences Python pour analyser les résultats de l'analyse en matière de problèmes de sécurité, en identifiant les services potentiellement risqués et en générant un rapport de sécurité complet.

Ces compétences sont essentielles pour les professionnels de la cybersécurité qui doivent effectuer des évaluations de réseau, des analyses de vulnérabilités et des audits de sécurité. La capacité d'automatiser l'analyse des résultats Nmap permet une surveillance de la sécurité plus efficace et plus approfondie.

Vous pouvez améliorer davantage ces compétences en :

  • Explorant des techniques d'analyse Nmap plus avancées
  • Intégrant les résultats de l'analyse à d'autres outils de sécurité
  • Créant des algorithmes d'analyse plus sophistiqués
  • Développant des outils de visualisation pour les données d'analyse

N'oubliez pas que l'analyse du réseau ne doit être effectuée que sur les réseaux que vous possédez ou pour lesquels vous avez l'autorisation explicite d'effectuer une analyse, car une analyse non autorisée peut être illégale et contraire à l'éthique.