Besoin d'un audit de sécurité ?
Devis personnalisé sous 24h
Virtualisation & Infrastructure

ESXi Hardening : Guide Complet de Sécurisation Avancée de l'Hyperviseur VMware

Par Ayi NEDJIMI 1 mars 2026 Lecture : 35 min ~6000 mots
#ESXiHardening #VMware #vSphere #Hyperviseur #SecureBoot #PowerCLI

1. Introduction : pourquoi le hardening ESXi est critique

L'hyperviseur VMware ESXi constitue la couche fondamentale sur laquelle reposent des milliers de machines virtuelles dans les datacenters du monde entier. Compromettre un seul hôte ESXi, c'est potentiellement prendre le contrôle de dizaines, voire de centaines de serveurs virtuels en une seule opération. Les groupes de ransomware l'ont parfaitement compris : depuis 2021, les attaques ciblant directement ESXi se sont multipliées de manière exponentielle, avec des familles comme ESXiArgs, Royal, Black Basta, LockBit et Akira qui intègrent désormais des modules de chiffrement spécifiques à VMFS.

Les chiffres sont alarmants : selon le rapport VMware Threat Landscape 2025, plus de 67 % des environnements vSphere audités présentent au moins une vulnérabilité critique non corrigée, et 43 % des hôtes ESXi exposent encore le service SSH en permanence. Le CERT-FR a émis pas moins de 12 alertes majeures concernant des vulnérabilités ESXi entre 2024 et 2025, dont plusieurs exploitées activement dans la nature (CVE-2024-37085, CVE-2025-22224, CVE-2025-22225).

La surface d'attaque d'un hyperviseur ESXi est vaste et multidimensionnelle. Elle englobe les interfaces de gestion (vSphere Client, API REST, DCUI), les services réseau (SSH, NTP, Syslog), la couche stockage (VMFS, NFS, iSCSI), les mécanismes d'authentification, et les interactions avec les machines virtuelles elles-mêmes. Chacune de ces composantes, si elle n'est pas correctement durcie, représente un vecteur d'entrée potentiel pour un attaquant déterminé.

Ce guide exhaustif couvre l'ensemble des mesures de durcissement applicables à VMware ESXi 7.x et 8.x, en s'appuyant sur les recommandations du VMware Security Configuration Guide (SCG), du DISA STIG ESXi, et du CIS Benchmark for VMware ESXi. Chaque recommandation est accompagnée de commandes concrètes, de scripts PowerCLI et d'indicateurs de conformité. Pour une vue d'ensemble sur les différents hyperviseurs disponibles et leurs modèles de sécurité respectifs, consultez notre comparatif de sécurité Proxmox vs VMware vs Hyper-V.

Principe fondamental : Un hyperviseur non durci est une bombe à retardement. La compromission de la couche de virtualisation contourne par conception tous les contrôles de sécurité déployés au niveau des machines virtuelles -- antivirus, EDR, pare-feu, chiffrement disque. Le hardening ESXi n'est pas optionnel, c'est une obligation.

Avertissement : compatibilité et tests

Avant d'appliquer les mesures de durcissement décrites dans ce guide, testez systématiquement chaque modification dans un environnement de qualification. Certains réglages peuvent impacter la compatibilité avec des solutions tierces (sauvegarde, monitoring, orchestration). Documentez chaque changement dans un registre de configuration et prévoyez une procédure de rollback.

Surface d'attaque de l'hyperviseur ESXi VMware ESXi VMkernel / Hyperviseur bare-metal Ring -1 (VMX root mode) SSH / DCUI / Shell Port 22 / Console vSphere Client / API Port 443 / REST API Réseau / vSwitch VLAN / Promiscuous Stockage VMFS iSCSI / NFS / vSAN Machines Virtuelles VM Escape / VMX Authentification AD / LDAP / Local Couche de durcissement (Hardening) Lockdown Mode + Firewall + STIG + Chiffrement + Audit Vecteurs d'attaque Composants cibles Mesures de protection

2. Sécurisation de l'accès ESXi

2.1 Lockdown Mode : le premier rempart

Le Lockdown Mode est le mécanisme de sécurité le plus fondamental et paradoxalement le plus sous-utilisé d'ESXi. Lorsqu'il est activé, il restreint l'accès direct à l'hôte ESXi en forçant toutes les opérations d'administration à transiter par vCenter Server. Deux niveaux existent :

Mode Comportement Accès autorisés Recommandation
Normal Lockdown Accès via vCenter uniquement vCenter, DCUI (utilisateurs exception list), services tiers autorisés Minimum requis en production
Strict Lockdown Accès via vCenter exclusivement vCenter uniquement. DCUI désactivé. Aucun accès direct possible. Environnements à haute sécurité (PCI-DSS, HDS)

Activation du Lockdown Mode via PowerCLI

# Connexion à vCenter
Connect-VIServer -Server vcenter.domaine.local -User admin@vsphere.local

# Activer le Lockdown Mode Normal sur tous les hôtes
Get-VMHost | ForEach-Object {
    $lockdown = Get-View $_.ExtensionData.ConfigManager.HostAccessManager
    $lockdown.ChangeLockdownMode("lockdownNormal")
    Write-Host "Lockdown Normal activé sur $($_.Name)" -ForegroundColor Green
}

# Pour le mode Strict (environnements critiques)
Get-VMHost | ForEach-Object {
    $lockdown = Get-View $_.ExtensionData.ConfigManager.HostAccessManager
    $lockdown.ChangeLockdownMode("lockdownStrict")
    Write-Host "Lockdown Strict activé sur $($_.Name)" -ForegroundColor Yellow
}

# Vérification de l'état actuel
Get-VMHost | Select-Object Name, @{N="LockdownMode";E={
    (Get-View $_.ExtensionData.ConfigManager.HostAccessManager).LockdownMode
}} | Format-Table -AutoSize

Bonne pratique : Exception List

Avant d'activer le Strict Lockdown, configurez une Exception List contenant au minimum un compte de service de secours (break-glass account). Ce compte, protégé par un mot de passe complexe stocké en coffre-fort numérique, vous permettra de retrouver l'accès en cas de perte de connectivité avec vCenter. Testez le scénario de perte de vCenter avant de basculer en production.

2.2 SSH : désactiver, verrouiller, auditer

Le service SSH sur ESXi est l'un des vecteurs d'attaque les plus exploités. Les groupes APT comme UNC3886 (Mandiant) ont démontré leur capacité à installer des backdoors persistantes via SSH sur des hôtes ESXi compromis. La règle est simple : SSH doit être désactivé en permanence et activé uniquement à la demande, pour une durée limitée, avec une trace d'audit.

# Désactiver SSH sur tous les hôtes
Get-VMHost | ForEach-Object {
    $sshService = Get-VMHostService -VMHost $_ | Where-Object { $_.Key -eq "TSM-SSH" }
    if ($sshService.Running) {
        Stop-VMHostService -HostService $sshService -Confirm:$false
        Write-Host "SSH arrêté sur $($_.Name)" -ForegroundColor Green
    }
    # Désactiver le démarrage automatique
    Set-VMHostService -HostService $sshService -Policy "Off"
}

# Configurer le timeout SSH (si SSH doit être activé temporairement)
Get-VMHost | Get-AdvancedSetting -Name "UserVars.ESXiShellTimeOut" | 
    Set-AdvancedSetting -Value 900 -Confirm:$false  # 15 minutes max

# Configurer le timeout interactif du shell
Get-VMHost | Get-AdvancedSetting -Name "UserVars.ESXiShellInteractiveTimeOut" | 
    Set-AdvancedSetting -Value 900 -Confirm:$false

# Bannière d'avertissement légale
$banner = "Avertissement : Acces reserve au personnel autorise. Toute activite est journalisee et surveillee. Tout acces non autorise est passible de poursuites."
Get-VMHost | Get-AdvancedSetting -Name "Config.Etc.issue" | 
    Set-AdvancedSetting -Value $banner -Confirm:$false

Alerte : ESXiArgs et variantes

Le ransomware ESXiArgs (février 2023) et ses variantes exploitent spécifiquement les services SLP et SSH exposés sur les hôtes ESXi. Si SSH est activé et que le port 22 est accessible depuis un réseau compromis, l'attaquant peut déployer un chiffreur VMFS en quelques minutes. Nos équipes ont documenté les techniques de kill chain ransomware et les contre-mesures associées dans un article dédié.

2.3 DCUI : contrôle de la console directe

La Direct Console User Interface (DCUI) est l'interface texte accessible depuis la console physique ou via iLO/iDRAC/IPMI. En mode Lockdown Normal, la DCUI reste accessible aux utilisateurs de la liste d'exception. En mode Strict, elle est entièrement désactivée. Pour les environnements intermédiaires, il est recommandé de :

  • Limiter les utilisateurs autorisés à accéder à la DCUI via la DCUI Access List
  • Configurer un mot de passe de verrouillage DCUI distinct du mot de passe root
  • Désactiver le service DCUI si l'accès physique est contrôlé et que IPMI est sécurisé
  • Surveiller les connexions DCUI dans les journaux d'audit (vobd.log)
# Désactiver le service DCUI
Get-VMHost | ForEach-Object {
    $dcuiService = Get-VMHostService -VMHost $_ | Where-Object { $_.Key -eq "DCUI" }
    Set-VMHostService -HostService $dcuiService -Policy "Off"
}

# Supprimer l'accès root à la DCUI (liste d'exception vide)
Get-VMHost | Get-AdvancedSetting -Name "DCUI.Access" | 
    Set-AdvancedSetting -Value "" -Confirm:$false

2.4 Sécurisation de l'interface web et de l'API

L'interface web de gestion d'ESXi (Host Client sur le port 443) et l'API REST constituent des cibles de choix. Plusieurs mesures s'imposent :

Configuration TLS renforcée

# Forcer TLS 1.2 minimum (désactiver TLS 1.0 et 1.1)
Get-VMHost | Get-AdvancedSetting -Name "UserVars.ESXiVPsDisabledProtocols" | 
    Set-AdvancedSetting -Value "sslv3,tlsv1,tlsv1.1" -Confirm:$false

# Vérifier les suites de chiffrement
esxcli system security fips140 ssh get

# Remplacer le certificat auto-signé par un certificat d'entreprise
# (à exécuter depuis le shell ESXi)
# cp /etc/vmware/ssl/rui.crt /etc/vmware/ssl/rui.crt.bak
# cp /etc/vmware/ssl/rui.key /etc/vmware/ssl/rui.key.bak
# cp /path/to/enterprise-cert.crt /etc/vmware/ssl/rui.crt
# cp /path/to/enterprise-key.key /etc/vmware/ssl/rui.key
# /etc/init.d/hostd restart

L'utilisation de certificats d'entreprise émis par une PKI interne est fortement recommandée. Les certificats auto-signés d'ESXi empêchent toute validation de confiance et facilitent les attaques de type Man-in-the-Middle. Pour une approche complète de la gestion des certificats dans un environnement Active Directory, notre article sur l'exploitation ADCS détaille les risques et les bonnes pratiques.

Verrouillage des comptes et politique de mots de passe

# Configurer le verrouillage après tentatives échouées
Get-VMHost | Get-AdvancedSetting -Name "Security.AccountLockFailures" | 
    Set-AdvancedSetting -Value 5 -Confirm:$false

# Durée de verrouillage (en secondes) - 15 minutes
Get-VMHost | Get-AdvancedSetting -Name "Security.AccountUnlockTime" | 
    Set-AdvancedSetting -Value 900 -Confirm:$false

# Politique de complexité des mots de passe
# Format: retry=N min=N1,N2,N3,N4,N5
# N1=longueur min pour 1 classe de caractères
# N2=longueur min pour 2 classes
# N3=longueur min pour passphrase
# N4=longueur min pour 3 classes
# N5=longueur min pour 4 classes
Get-VMHost | Get-AdvancedSetting -Name "Security.PasswordQualityControl" | 
    Set-AdvancedSetting -Value "retry=3 min=disabled,disabled,disabled,disabled,15" -Confirm:$false

# Historique des mots de passe
Get-VMHost | Get-AdvancedSetting -Name "Security.PasswordHistory" | 
    Set-AdvancedSetting -Value 5 -Confirm:$false

3. Configuration réseau sécurisée

3.1 Architecture vSwitch et isolation réseau

La segmentation réseau au niveau de l'hyperviseur est un pilier fondamental de la sécurité. Un vSwitch Standard (vSS) ou vSwitch Distribué (vDS) mal configuré peut permettre à un attaquant ayant compromis une VM d'intercepter le trafic réseau de toutes les autres VM du même hôte. Les principes de segmentation doivent être appliqués avec rigueur :

Type de trafic vSwitch dédié VLAN Politique de sécurité
Management (VMkernel) vSwitch0 (dédié) VLAN 10 Accès restreint, ACL pare-feu
vMotion vSwitch1 (dédié) VLAN 20 Chiffré (vMotion Encryption)
Stockage (iSCSI/NFS) vSwitch2 (dédié) VLAN 30 Jumbo Frames, CHAP
VM Production vSwitch3 VLAN 100-199 Port Groups isolés
VM DMZ vSwitch4 (dédié) VLAN 200 Isolation stricte
vSAN vSwitch5 (dédié) VLAN 40 Chiffrement en transit

Politiques de sécurité des Port Groups

Chaque port group possède trois politiques de sécurité critiques qui doivent être configurées explicitement :

# Désactiver le mode promiscuous sur tous les port groups
Get-VirtualSwitch | Get-SecurityPolicy | 
    Set-SecurityPolicy -AllowPromiscuous $false -ForgedTransmits $false -MacChanges $false

# Vérification détaillée de la configuration
Get-VMHost | ForEach-Object {
    $vmhost = $_
    Get-VirtualSwitch -VMHost $vmhost | ForEach-Object {
        $vswitch = $_
        Get-VirtualPortGroup -VirtualSwitch $vswitch | ForEach-Object {
            $policy = Get-SecurityPolicy -VirtualPortGroup $_
            [PSCustomObject]@{
                Host = $vmhost.Name
                vSwitch = $vswitch.Name
                PortGroup = $_.Name
                VLAN = $_.VLanId
                Promiscuous = $policy.AllowPromiscuous
                ForgedTransmits = $policy.ForgedTransmits
                MACChanges = $policy.MacChanges
            }
        }
    }
} | Format-Table -AutoSize

# Configurer le VLAN trunking correctement
# VLAN 4095 = trunk mode (DANGER : à utiliser uniquement si nécessaire)
# Préférer un VLAN ID spécifique pour chaque port group
Get-VirtualPortGroup -Name "Production-VMs" | Set-VirtualPortGroup -VLanId 100

Règle d'or : zéro promiscuous mode

Le mode promiscuous permet à une VM de capturer tout le trafic transitant par le vSwitch, y compris les paquets destinés à d'autres VM. Cette fonctionnalité ne doit jamais être activée sur un port group de production. Les seules exceptions acceptables sont les VM dédiées au monitoring réseau (IDS/IPS) ou les appliances de capture de trafic, et même dans ces cas, utilisez un port group dédié avec un VLAN isolé. L'activation non autorisée du mode promiscuous est un indicateur de compromission majeur, comme nous l'expliquons dans notre guide sur la détection d'exfiltration furtive.

3.2 Pare-feu ESXi : configuration avancée

ESXi intègre un pare-feu stateful configurable qui contrôle les connexions entrantes et sortantes. Par défaut, de nombreuses règles sont trop permissives. Un durcissement rigoureux est nécessaire :

# Lister toutes les règles de pare-feu
Get-VMHost | Get-VMHostFirewallException | 
    Select-Object Name, Enabled, IncomingPorts, OutgoingPorts, Protocols | 
    Format-Table -AutoSize

# Désactiver les services non nécessaires
$servicesToDisable = @(
    "CIMHttpServer",      # CIM sur HTTP (non chiffré)
    "CIMHttpsServer",     # CIM sur HTTPS (si non utilisé)
    "CIMSLP",             # Service Location Protocol (exploité par ESXiArgs)
    "DHCPv6",             # IPv6 DHCP (si IPv6 non utilisé)
    "DVFilter",           # DVFilter (si non utilisé)
    "HBX",                # Heartbeat
    "ipfam",              # IP Fault Management
    "WOL"                 # Wake on LAN
)

Get-VMHost | ForEach-Object {
    $vmhost = $_
    foreach ($svc in $servicesToDisable) {
        $rule = Get-VMHostFirewallException -VMHost $vmhost -Name $svc -ErrorAction SilentlyContinue
        if ($rule -and $rule.Enabled) {
            Set-VMHostFirewallException -Exception $rule -Enabled $false
            Write-Host "Règle $svc désactivée sur $($vmhost.Name)" -ForegroundColor Green
        }
    }
}

# Restreindre l'accès SSH à des IP spécifiques (via esxcli)
# esxcli network firewall ruleset set -r sshServer -e true
# esxcli network firewall ruleset allowedip add -r sshServer -i 10.0.1.0/24
# esxcli network firewall ruleset set -r sshServer -a false

# Restreindre l'accès vSphere Client à des IP spécifiques
# esxcli network firewall ruleset allowedip add -r webAccess -i 10.0.1.0/24
# esxcli network firewall ruleset set -r webAccess -a false

SLP : le service à désactiver en urgence

Le Service Location Protocol (SLP) sur le port 427 a été le vecteur d'entrée principal de l'attaque ESXiArgs. Ce service, utilisé pour la découverte de services CIM, est rarement nécessaire en production. Désactivez-le immédiatement sur tous vos hôtes ESXi : esxcli network firewall ruleset set -r CIMSLP -e false et /etc/init.d/slpd stop. La vulnérabilité CVE-2021-21974 exploite spécifiquement ce service.

3.3 Chiffrement vMotion et isolation du trafic de management

Le trafic vMotion transporte l'intégralité de la mémoire d'une VM en temps réel lors d'une migration. Sans chiffrement, un attaquant positionné sur le réseau vMotion peut intercepter des données sensibles -- clés de chiffrement, mots de passe en mémoire, tokens d'authentification. Depuis vSphere 6.5, le chiffrement vMotion est disponible et doit être systématiquement activé :

# Activer le chiffrement vMotion sur toutes les VMs
Get-VM | ForEach-Object {
    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $spec.MigrateEncryption = "opportunistic"  # ou "required" pour forcer
    $_.ExtensionData.ReconfigVM($spec)
    Write-Host "Chiffrement vMotion configuré sur $($_.Name)" -ForegroundColor Green
}

# Vérifier l'état du chiffrement vMotion
Get-VM | Select-Object Name, @{N="MigrateEncryption";E={
    $_.ExtensionData.Config.MigrateEncryption
}} | Format-Table -AutoSize

4. Hardening du stockage

4.1 Sécurisation VMFS et datastores

Les datastores VMFS contiennent les fichiers les plus critiques de votre infrastructure : les disques virtuels (VMDK), les fichiers de configuration (VMX), les snapshots et les fichiers swap. La compromission d'un datastore signifie l'accès direct aux données de toutes les VM qu'il héberge. Plusieurs couches de protection doivent être mises en place :

Permissions sur les datastores

# Vérifier les permissions sur les datastores
Get-Datastore | ForEach-Object {
    $ds = $_
    $permissions = Get-VIPermission -Entity $ds
    [PSCustomObject]@{
        Datastore = $ds.Name
        Capacité = "{0:N2} GB" -f ($ds.CapacityGB)
        Utilisé = "{0:N2} GB" -f (($ds.CapacityGB - $ds.FreeSpaceGB))
        Permissions = ($permissions | ForEach-Object { "$($_.Principal):$($_.Role)" }) -join "; "
    }
} | Format-Table -AutoSize

# Vérifier l'accès aux fichiers VMDK depuis l'hôte
# (via esxcli - exécuter en SSH si nécessaire)
# ls -la /vmfs/volumes/datastore1/
# Vérifier que les fichiers .vmdk et .vmx ont les bonnes permissions

4.2 Sécurisation iSCSI avec CHAP

Pour les environnements utilisant iSCSI comme protocole de stockage, l'authentification CHAP (Challenge-Handshake Authentication Protocol) est indispensable. Sans CHAP, n'importe quel hôte du réseau de stockage peut monter les LUN et accéder aux données. Utilisez de préférence le CHAP mutuel (bidirectionnel) qui authentifie à la fois l'initiateur et la cible :

# Configurer CHAP sur l'adaptateur iSCSI
$vmhost = Get-VMHost "esxi01.domaine.local"
$hba = Get-VMHostHba -VMHost $vmhost -Type iScsi

# CHAP unidirectionnel (minimum requis)
$authParams = New-Object VMware.Vim.HostInternetScsiHbaAuthenticationProperties
$authParams.ChapAuthEnabled = $true
$authParams.ChapAuthenticationType = "chapRequired"
$authParams.ChapName = "esxi01-iscsi"
$authParams.ChapSecret = "MotDePasseComplexe32Caracteres!!"

# CHAP mutuel (recommandé)
$authParams.MutualChapAuthenticationType = "chapRequired"
$authParams.MutualChapName = "storage-target-01"
$authParams.MutualChapSecret = "SecretMutuelComplexe32Chars!!"

# Application
$storageSystem = Get-View $vmhost.ExtensionData.ConfigManager.StorageSystem
$storageSystem.UpdateInternetScsiAuthenticationProperties(
    $hba.ExtensionData.Device, $authParams
)
Write-Host "CHAP mutuel configuré sur $($vmhost.Name)" -ForegroundColor Green

4.3 NFS Security : authentification Kerberos

Les datastores NFS v3 n'offrent aucune authentification native -- l'accès est contrôlé uniquement par l'adresse IP. NFS v4.1 avec Kerberos apporte l'authentification mutuelle et le chiffrement en transit, ce qui en fait le choix obligatoire pour les environnements sécurisés :

# Vérifier la version NFS utilisée
Get-VMHost | ForEach-Object {
    Get-Datastore -VMHost $_ | Where-Object { $_.Type -eq "NFS" } | 
    Select-Object Name, @{N="Host";E={$vmhost.Name}}, 
                  @{N="NFSVersion";E={$_.ExtensionData.Info.Nas.SecurityType}},
                  @{N="RemoteHost";E={$_.ExtensionData.Info.Nas.RemoteHost}},
                  @{N="RemotePath";E={$_.ExtensionData.Info.Nas.RemotePath}}
} | Format-Table -AutoSize

# Monter un datastore NFS 4.1 avec Kerberos
New-Datastore -VMHost "esxi01.domaine.local" -Name "NFS_Secure" `
    -Nfs -NfsHost "nfs-server.domaine.local" `
    -Path "/exports/vmware" `
    -FileSystemVersion "4.1" `
    -SecurityType "SEC_KRB5I"  # Intégrité Kerberos (SEC_KRB5P pour chiffrement)

4.4 Chiffrement au repos (VM Encryption et vSAN Encryption)

Le chiffrement au repos protège les données en cas d'accès physique non autorisé aux disques ou de vol de matériel. VMware propose deux approches complémentaires :

Méthode Scope KMS requis Impact performance Cas d'usage
VM Encryption Par VM individuelle Oui (KMIP) Faible (AES-NI) VMs sensibles, données personnelles
vSAN Encryption Cluster vSAN entier Oui (KMIP) Très faible Chiffrement global du stockage
vTPM Par VM (BitLocker/LUKS) Non (mais VM Encryption requise) Minimal Conformité Windows, Secure Boot
# Vérifier la configuration du KMS (Key Management Server)
Get-KeyProvider | Select-Object Name, Type, Status

# Activer le chiffrement sur une VM spécifique
$vm = Get-VM "VM-Sensible-01"
$storagePolicy = Get-SpbmStoragePolicy -Name "VM Encryption Policy"
Set-SpbmEntityConfiguration -Configuration (
    Get-SpbmEntityConfiguration -VM $vm
) -StoragePolicy $storagePolicy

# Vérifier l'état de chiffrement des VMs
Get-VM | Select-Object Name, @{N="Encrypted";E={
    $_.ExtensionData.Config.KeyId -ne $null
}}, @{N="KeyId";E={
    $_.ExtensionData.Config.KeyId.KeyId
}} | Where-Object { $_.Encrypted } | Format-Table -AutoSize

Point clé : architecture KMS

Le serveur KMS (Key Management Server) est le maillon critique de toute architecture de chiffrement vSphere. Si le KMS est indisponible, les VMs chiffrées ne pourront pas être déverrouillées après un redémarrage. Déployez obligatoirement un cluster KMS en haute disponibilité, avec des sauvegardes régulières des clés de chiffrement stockées hors site. Testez régulièrement la procédure de restauration KMS dans le cadre de vos tests PRA.

5. Gestion des comptes et privilèges

5.1 Intégration Active Directory

L'authentification locale sur chaque hôte ESXi (compte root) est un cauchemar de gestion et de sécurité. L'intégration avec Active Directory centralise l'authentification, permet l'application de politiques de mot de passe cohérentes et facilite la traçabilité des accès. Toutefois, cette intégration doit être réalisée avec précaution pour ne pas introduire de nouvelles vulnérabilités. Pour comprendre les risques associés à une compromission AD, consultez notre article sur l'exploitation Kerberos en environnement Active Directory.

# Joindre un hôte ESXi au domaine Active Directory
Get-VMHost "esxi01.domaine.local" | Get-VMHostAuthentication | 
    Set-VMHostAuthentication -JoinDomain -Domain "domaine.local" `
    -User "svc-esxi-join" -Password "MotDePasse" -Confirm:$false

# Vérifier l'état de jonction au domaine
Get-VMHost | Get-VMHostAuthentication | 
    Select-Object VMHost, Domain, DomainMembershipStatus | 
    Format-Table -AutoSize

# Attribuer le rôle Admin à un groupe AD spécifique (pas "Domain Admins" !)
$rootFolder = Get-Folder -NoRecursion
New-VIPermission -Entity $rootFolder -Principal "DOMAINE\GRP-vSphere-Admins" `
    -Role "Admin" -Propagate $true

Ne jamais utiliser "Domain Admins" pour l'accès vSphere

Nous observons régulièrement en audit des environnements où le groupe Domain Admins d'Active Directory dispose de droits administrateurs sur vCenter. C'est une erreur grave : la compromission d'un seul compte Domain Admin (via Kerberoasting, Pass-the-Hash ou phishing) donne alors un accès total à l'infrastructure de virtualisation. Créez un groupe AD dédié (GRP-vSphere-Admins) avec une membership strictement contrôlée et auditée.

5.2 Modèle de rôles et principe du moindre privilège

vSphere propose un système RBAC granulaire avec des rôles prédéfinis et la possibilité de créer des rôles personnalisés. L'application du principe du moindre privilège est essentielle :

Rôle personnalisé Privilèges Affecté à Scope
VM-Operator Power On/Off, Console, Snapshot Équipe exploitation Resource Pool spécifique
VM-Provisioner Create/Delete VM, Deploy template Équipe provisioning Cluster dédié
Network-Admin dvSwitch config, Port Group mgmt Équipe réseau Distributed vSwitch
Storage-Admin Datastore browse, Allocate space Équipe stockage Datastores spécifiques
Security-Auditor Read-Only global + Configuration view Équipe sécurité vCenter (global)
# Créer un rôle personnalisé VM-Operator
$privileges = @(
    "VirtualMachine.Interact.PowerOn",
    "VirtualMachine.Interact.PowerOff",
    "VirtualMachine.Interact.Reset",
    "VirtualMachine.Interact.ConsoleInteract",
    "VirtualMachine.State.CreateSnapshot",
    "VirtualMachine.State.RemoveSnapshot",
    "VirtualMachine.State.RevertToSnapshot"
)
New-VIRole -Name "VM-Operator" -Privilege (Get-VIPrivilege -Id $privileges)

# Affecter le rôle à un scope limité
$resourcePool = Get-ResourcePool "RP-Production"
New-VIPermission -Entity $resourcePool -Principal "DOMAINE\GRP-VM-Operators" `
    -Role "VM-Operator" -Propagate $true

# Auditer les permissions existantes
Get-VIPermission | Select-Object Entity, EntityId, Principal, Role, Propagate | 
    Sort-Object Role | Format-Table -AutoSize

5.3 Sécurisation du compte root et comptes de service

Le compte root d'ESXi est le compte le plus critique de l'hôte. Sa compromission donne un accès complet et non auditable au système. Les mesures suivantes sont impératives :

  • Mot de passe unique par hôte : chaque ESXi doit avoir un mot de passe root différent, généré aléatoirement (32 caractères minimum) et stocké dans un coffre-fort de mots de passe (CyberArk, HashiCorp Vault, KeePass en dernier recours)
  • Rotation régulière : changement tous les 90 jours au minimum, automatisé via un outil PAM (Privileged Access Management)
  • Pas d'utilisation directe : le compte root ne doit être utilisé qu'en situation d'urgence (break-glass procedure). Les opérations quotidiennes passent par des comptes AD nominatifs
  • Suppression des comptes locaux inutiles : auditez et supprimez tout compte local non documenté
# Auditer les comptes locaux sur chaque hôte ESXi
Get-VMHost | ForEach-Object {
    $vmhost = $_
    $esxcli = Get-EsxCli -VMHost $vmhost -V2
    $accounts = $esxcli.system.account.list.Invoke()
    $accounts | ForEach-Object {
        [PSCustomObject]@{
            Host = $vmhost.Name
            UserID = $_.UserID
            Description = $_.Description
        }
    }
} | Format-Table -AutoSize

# Supprimer un compte local non autorisé
# esxcli system account remove -i "compte-suspect"
Défense en profondeur ESXi - 5 couches de protection 1. Sécurité physique & réseau Contrôle d'accès datacenter, segmentation VLAN, pare-feu périmétrique, iLO/IPMI sécurisé 2. Authentification & contrôle d'accès Lockdown Mode, AD intégration, RBAC, MFA, comptes de service gérés, PAM 3. Configuration durcie (hardening) SSH off, SLP off, TLS 1.2+, banner, timeout, firewall rules, STIG compliance 4. Chiffrement & intégrité VM Encryption, vMotion Encryption, Secure Boot, vTPM, VMFS chiffré 5. Monitoring & réponse Syslog centralisé, SIEM intégration, alertes temps réel Compliance scanning, drift detection, incident response PROFONDEUR →

6. Sécurisation des machines virtuelles

6.1 Secure Boot des VMs

Le Secure Boot au niveau de la VM garantit que seul un firmware et un boot loader signés numériquement peuvent être exécutés au démarrage. Cette mesure empêche l'injection de bootkits et rootkits au niveau du firmware de la VM, une technique utilisée par des APT sophistiqués que nous détaillons dans notre article sur les UEFI bootkits et la persistance firmware.

# Activer Secure Boot sur les VMs (nécessite firmware EFI)
Get-VM | Where-Object { $_.ExtensionData.Config.Firmware -eq "efi" } | ForEach-Object {
    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $boot = New-Object VMware.Vim.VirtualMachineBootOptions
    $boot.EfiSecureBootEnabled = $true
    $spec.BootOptions = $boot
    $_.ExtensionData.ReconfigVM($spec)
    Write-Host "Secure Boot activé sur $($_.Name)" -ForegroundColor Green
}

# Vérifier l'état du Secure Boot
Get-VM | Select-Object Name, 
    @{N="Firmware";E={$_.ExtensionData.Config.Firmware}},
    @{N="SecureBoot";E={$_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled}} | 
    Format-Table -AutoSize

6.2 vTPM (Virtual Trusted Platform Module)

Le vTPM 2.0 fournit un module de plateforme sécurisé virtuel aux VMs, permettant d'activer des fonctionnalités de sécurité avancées comme BitLocker (Windows), LUKS avec TPM (Linux), ou Windows Credential Guard. Le vTPM nécessite que la VM soit chiffrée (VM Encryption) car les données TPM doivent être protégées :

# Ajouter un vTPM à une VM existante (nécessite VM Encryption active)
$vm = Get-VM "Win-Server-2025-01"
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$tpmDevice = New-Object VMware.Vim.VirtualTPM
$deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec
$deviceChange.Operation = "add"
$deviceChange.Device = $tpmDevice
$spec.DeviceChange += $deviceChange
$vm.ExtensionData.ReconfigVM($spec)
Write-Host "vTPM ajouté à $($vm.Name)" -ForegroundColor Green

# Vérifier les VMs avec vTPM
Get-VM | ForEach-Object {
    $hasTPM = $_.ExtensionData.Config.Hardware.Device | 
              Where-Object { $_ -is [VMware.Vim.VirtualTPM] }
    if ($hasTPM) {
        [PSCustomObject]@{
            VM = $_.Name
            vTPM = "Oui"
            Firmware = $_.ExtensionData.Config.Firmware
        }
    }
} | Format-Table -AutoSize

6.3 VBS (Virtualization-Based Security) et isolation mémoire

La Virtualization-Based Security (VBS) est une technologie Microsoft qui utilise les capacités de virtualisation matérielle pour créer une zone de mémoire isolée au sein même de la VM. Cette zone héberge des processus critiques comme Credential Guard (protection des secrets LSASS), Hypervisor-Protected Code Integrity (HVCI) et Windows Defender Application Guard. Pour l'activer dans vSphere :

# Activer le support VBS sur une VM Windows
$vm = Get-VM "Win-Server-2025-01"
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.Flags = New-Object VMware.Vim.VirtualMachineFlagInfo
$spec.Flags.VbsEnabled = $true
$spec.Flags.VvtdEnabled = $true  # Intel VT-d pour IOMMU virtuel
$vm.ExtensionData.ReconfigVM($spec)

# Vérifier le support VBS
Get-VM | Select-Object Name, @{N="VBS";E={
    $_.ExtensionData.Config.Flags.VbsEnabled
}} | Where-Object { $_.VBS } | Format-Table -AutoSize

6.4 Isolation et paramètres avancés de sécurité des VMs

Plusieurs paramètres avancés au niveau de la VM renforcent l'isolation entre l'hôte et les machines virtuelles, réduisant ainsi la surface d'attaque pour les techniques de VM Escape :

# Désactiver les fonctionnalités d'interaction non nécessaires
$securitySettings = @{
    "isolation.tools.copy.disable" = "TRUE"           # Copier-coller désactivé
    "isolation.tools.paste.disable" = "TRUE"           # Coller désactivé
    "isolation.tools.diskShrink.disable" = "TRUE"      # Shrink disk désactivé
    "isolation.tools.diskWiper.disable" = "TRUE"       # Wipe disk désactivé
    "isolation.tools.hgfsServerSet.disable" = "TRUE"   # HGFS désactivé
    "isolation.tools.ghi.autologon.disable" = "TRUE"   # Auto-logon désactivé
    "isolation.tools.ghi.launchMenu.change" = "TRUE"   # Launch menu désactivé
    "isolation.tools.unity.disable" = "TRUE"           # Unity mode désactivé
    "isolation.tools.unityInterlockOperation.disable" = "TRUE"
    "isolation.tools.getCreds.disable" = "TRUE"        # GetCreds désactivé
    "isolation.tools.setGUIOptions.enable" = "FALSE"
    "mks.enable3d" = "FALSE"                           # 3D désactivé
    "tools.setInfo.sizeLimit" = "1048576"             # Limite taille SetInfo (1 MB)
    "RemoteDisplay.maxConnections" = "1"               # Max 1 connexion console
    "log.keepOld" = "10"                               # Rétention logs VM
    "log.rotateSize" = "2048000"                       # Taille rotation logs
    "tools.guestlib.enableHostInfo" = "FALSE"          # Info hôte masquée
}

# Appliquer sur toutes les VMs
Get-VM | ForEach-Object {
    $vm = $_
    foreach ($setting in $securitySettings.GetEnumerator()) {
        $existingSetting = Get-AdvancedSetting -Entity $vm -Name $setting.Key -ErrorAction SilentlyContinue
        if ($existingSetting) {
            Set-AdvancedSetting -AdvancedSetting $existingSetting -Value $setting.Value -Confirm:$false
        } else {
            New-AdvancedSetting -Entity $vm -Name $setting.Key -Value $setting.Value -Confirm:$false
        }
    }
    Write-Host "Paramètres de sécurité appliqués sur $($vm.Name)" -ForegroundColor Green
}

VM Escape : une menace réelle

Les vulnérabilités de type VM Escape permettent à un attaquant de sortir du contexte d'une machine virtuelle pour exécuter du code sur l'hyperviseur. Bien que rares, elles sont dévastatrices : CVE-2023-20867 (VMware Tools), CVE-2024-22252 (contrôleur USB XHCI) en sont des exemples récents. Les paramètres d'isolation ci-dessus réduisent significativement la surface d'attaque exploitable. Pour les détails sur les techniques d'évasion de sandbox, notre article sur le container escape Docker/containerd couvre des concepts analogues applicables au contexte de virtualisation.

7. Logging, monitoring et conformité

7.1 Configuration Syslog centralisée

La journalisation centralisée est indispensable pour la détection d'intrusion, l'investigation forensique et la conformité réglementaire. Les hôtes ESXi génèrent des logs critiques dans plusieurs fichiers : hostd.log (opérations d'administration), vpxa.log (communications vCenter), auth.log (authentifications), vmkernel.log (kernel et réseau), et vobd.log (observations système). Tous ces logs doivent être envoyés vers un serveur Syslog centralisé, idéalement intégré à un SIEM. Pour une méthodologie complète de corrélation de logs dans un contexte d'investigation, consultez notre article sur la timeline forensique et la chronologie d'intrusion.

# Configurer Syslog sur tous les hôtes ESXi
$syslogServer = "udp://siem.domaine.local:514"
# Pour TLS (recommandé) : "ssl://siem.domaine.local:6514"

Get-VMHost | ForEach-Object {
    # Configurer le serveur Syslog distant
    Set-VMHostSysLogServer -VMHost $_ -SysLogServer $syslogServer
    
    # Configurer la rétention locale (en jours)
    Get-AdvancedSetting -Entity $_ -Name "Syslog.global.logDir" | 
        Set-AdvancedSetting -Value "[]/scratch/log" -Confirm:$false
    
    # Configurer la rotation des logs
    Get-AdvancedSetting -Entity $_ -Name "Syslog.global.logDirUnique" | 
        Set-AdvancedSetting -Value $true -Confirm:$false
    
    # Taille maximale des fichiers log (en Ko)
    Get-AdvancedSetting -Entity $_ -Name "Syslog.global.defaultRotate" | 
        Set-AdvancedSetting -Value 20 -Confirm:$false
    
    # Nombre de rotations conservées
    Get-AdvancedSetting -Entity $_ -Name "Syslog.global.defaultSize" | 
        Set-AdvancedSetting -Value 10240 -Confirm:$false
    
    # Ouvrir le port de pare-feu pour Syslog
    $fwRule = Get-VMHostFirewallException -VMHost $_ -Name "syslog"
    Set-VMHostFirewallException -Exception $fwRule -Enabled $true
    
    Write-Host "Syslog configuré sur $($_.Name) -> $syslogServer" -ForegroundColor Green
}

# Vérification
Get-VMHost | Get-VMHostSysLogServer | Format-Table -AutoSize

# Forcer la synchronisation NTP (essentiel pour la corrélation de logs)
Get-VMHost | ForEach-Object {
    $ntpService = Get-VMHostService -VMHost $_ | Where-Object { $_.Key -eq "ntpd" }
    Start-VMHostService -HostService $ntpService -Confirm:$false
    Set-VMHostService -HostService $ntpService -Policy "On"
    
    # Configurer les serveurs NTP
    Add-VMHostNtpServer -VMHost $_ -NtpServer @("ntp1.domaine.local", "ntp2.domaine.local") -ErrorAction SilentlyContinue
    
    # Redémarrer le service NTP
    Restart-VMHostService -HostService $ntpService -Confirm:$false
}

Attention : syslog sur UDP n'est pas sûr

L'envoi de logs via UDP (port 514) est sujet à la perte de paquets et ne fournit aucun chiffrement ni authentification. En environnement de production, utilisez Syslog over TLS (port 6514) avec un certificat de confiance. Cela garantit la confidentialité des logs en transit et l'intégrité des données. Pour les environnements soumis à des exigences réglementaires (ISO 27001, NIS 2), le chiffrement des logs en transit est une obligation.

7.2 Intégration SIEM et règles de détection

L'envoi des logs ESXi vers un SIEM permet la corrélation avec d'autres sources de données (Active Directory, pare-feu, EDR) et la détection automatisée de comportements suspects. Voici les événements critiques à surveiller :

Événement Source de log Sévérité Règle SIEM recommandée
Activation SSH hostd.log Haute Alerte immédiate + ticket
Échec d'authentification root (> 3) auth.log Critique Alerte + blocage IP source
Connexion root réussie auth.log Haute Notification + vérification
Modification Lockdown Mode vpxa.log Critique Alerte immédiate
Installation VIB non signé esxupdate.log Critique Alerte + isolation hôte
Modification règle pare-feu hostd.log Haute Alerte + audit
Changement de politique vSwitch hostd.log Haute Alerte + vérification promiscuous
Export/copie VMDK hostd.log Haute Alerte exfiltration potentielle
# Exemple de requête Splunk pour détecter l'activation SSH
# index=esxi sourcetype=vmware:esxi:hostd "SSH" "enabled"
# | stats count by host, _time
# | where count > 0

# Exemple de requête Elastic/KQL
# event.dataset: "vmware.esxi" AND message: "SSH" AND message: "enabled"

# Exemple de règle Sigma (format universel)
# title: ESXi SSH Service Enabled
# status: experimental
# logsource:
#   product: vmware
#   service: hostd
# detection:
#   selection:
#     message|contains|all:
#       - "SSH"
#       - "enabled"
#   condition: selection
# level: high

7.3 Conformité STIG et CIS Benchmark

Deux référentiels majeurs encadrent le durcissement d'ESXi. Le DISA STIG (Security Technical Implementation Guide) est obligatoire pour les environnements gouvernementaux américains et constitue une référence de l'industrie. Le CIS Benchmark propose des profils Level 1 (essentiel) et Level 2 (renforcé). Les deux référentiels couvrent des domaines similaires mais avec des niveaux de granularité différents :

# Script de vérification de conformité STIG ESXi 8 (extrait)
function Test-ESXiSTIGCompliance {
    param([string]$VMHostName)
    
    $vmhost = Get-VMHost $VMHostName
    $results = @()
    
    # STIG V-258706: SSH must be disabled
    $ssh = Get-VMHostService -VMHost $vmhost | Where-Object { $_.Key -eq "TSM-SSH" }
    $results += [PSCustomObject]@{
        STIG_ID = "V-258706"
        Check = "SSH Service Disabled"
        Status = if (-not $ssh.Running) { "PASS" } else { "FAIL" }
        Current = $ssh.Running
        Expected = $false
    }
    
    # STIG V-258707: Lockdown Mode must be enabled
    $lockdown = (Get-View $vmhost.ExtensionData.ConfigManager.HostAccessManager).LockdownMode
    $results += [PSCustomObject]@{
        STIG_ID = "V-258707"
        Check = "Lockdown Mode Enabled"
        Status = if ($lockdown -ne "lockdownDisabled") { "PASS" } else { "FAIL" }
        Current = $lockdown
        Expected = "lockdownNormal or lockdownStrict"
    }
    
    # STIG V-258708: Account lockout configured
    $lockFailures = (Get-AdvancedSetting -Entity $vmhost -Name "Security.AccountLockFailures").Value
    $results += [PSCustomObject]@{
        STIG_ID = "V-258708"
        Check = "Account Lockout Failures <= 5"
        Status = if ([int]$lockFailures -le 5 -and [int]$lockFailures -gt 0) { "PASS" } else { "FAIL" }
        Current = $lockFailures
        Expected = "1-5"
    }
    
    # STIG V-258710: NTP must be configured
    $ntpServers = Get-VMHostNtpServer -VMHost $vmhost
    $results += [PSCustomObject]@{
        STIG_ID = "V-258710"
        Check = "NTP Configured"
        Status = if ($ntpServers.Count -ge 1) { "PASS" } else { "FAIL" }
        Current = ($ntpServers -join ", ")
        Expected = "At least 1 NTP server"
    }
    
    # STIG V-258714: TLS 1.2 enforced
    $tlsConfig = (Get-AdvancedSetting -Entity $vmhost -Name "UserVars.ESXiVPsDisabledProtocols").Value
    $results += [PSCustomObject]@{
        STIG_ID = "V-258714"
        Check = "TLS 1.0/1.1 Disabled"
        Status = if ($tlsConfig -match "tlsv1,tlsv1.1" -or $tlsConfig -match "tlsv1.1,tlsv1") { "PASS" } else { "FAIL" }
        Current = $tlsConfig
        Expected = "sslv3,tlsv1,tlsv1.1"
    }
    
    # STIG V-258716: Syslog configured
    $syslog = Get-VMHostSysLogServer -VMHost $vmhost
    $results += [PSCustomObject]@{
        STIG_ID = "V-258716"
        Check = "Syslog Remote Server"
        Status = if ($syslog) { "PASS" } else { "FAIL" }
        Current = $syslog
        Expected = "Remote syslog server configured"
    }
    
    return $results
}

# Exécuter sur tous les hôtes
Get-VMHost | ForEach-Object {
    Write-Host "`n=== Conformité STIG: $($_.Name) ===" -ForegroundColor Cyan
    $compliance = Test-ESXiSTIGCompliance -VMHostName $_.Name
    $compliance | Format-Table -AutoSize
    
    $passCount = ($compliance | Where-Object { $_.Status -eq "PASS" }).Count
    $totalCount = $compliance.Count
    $percentage = [math]::Round(($passCount / $totalCount) * 100, 1)
    Write-Host "Score: $passCount/$totalCount ($percentage%)" -ForegroundColor $(if ($percentage -ge 80) { "Green" } else { "Red" })
}

8. Automatisation du hardening

8.1 Script PowerCLI complet de durcissement

L'automatisation du hardening est essentielle pour garantir la cohérence de la configuration à l'échelle de l'infrastructure et pour détecter les dérives (configuration drift). Le script suivant regroupe l'ensemble des mesures de durcissement abordées dans ce guide en un pipeline PowerCLI exécutable. Pour les équipes qui utilisent des techniques similaires d'automatisation dans l'écosystème Microsoft, notre article sur l'escalade de privilèges Windows détaille les contre-mesures automatisables via GPO et PowerShell.

# ============================================
# ESXi Hardening Script - Version 2026.03
# Auteur: Ayi NEDJIMI - ayinedjimi-consultants.fr
# ============================================

param(
    [Parameter(Mandatory=$true)]
    [string]$vCenterServer,
    
    [Parameter(Mandatory=$false)]
    [string]$SyslogServer = "ssl://siem.domaine.local:6514",
    
    [Parameter(Mandatory=$false)]
    [switch]$StrictLockdown,
    
    [Parameter(Mandatory=$false)]
    [switch]$WhatIf
)

# Connexion
Connect-VIServer -Server $vCenterServer

$allHosts = Get-VMHost
$totalChanges = 0

foreach ($vmhost in $allHosts) {
    Write-Host "`n========================================" -ForegroundColor Cyan
    Write-Host "Hardening: $($vmhost.Name)" -ForegroundColor Cyan
    Write-Host "========================================" -ForegroundColor Cyan
    
    # --- 1. Services ---
    Write-Host "`n[1/8] Configuration des services..." -ForegroundColor Yellow
    
    # Désactiver SSH
    $ssh = Get-VMHostService -VMHost $vmhost | Where-Object { $_.Key -eq "TSM-SSH" }
    if ($ssh.Running) {
        if (-not $WhatIf) { Stop-VMHostService -HostService $ssh -Confirm:$false }
        Write-Host "  [+] SSH arrêté" -ForegroundColor Green
        $totalChanges++
    }
    if (-not $WhatIf) { Set-VMHostService -HostService $ssh -Policy "Off" }
    
    # Désactiver ESXi Shell
    $shell = Get-VMHostService -VMHost $vmhost | Where-Object { $_.Key -eq "TSM" }
    if ($shell.Running) {
        if (-not $WhatIf) { Stop-VMHostService -HostService $shell -Confirm:$false }
        Write-Host "  [+] ESXi Shell arrêté" -ForegroundColor Green
        $totalChanges++
    }
    if (-not $WhatIf) { Set-VMHostService -HostService $shell -Policy "Off" }
    
    # Activer et configurer NTP
    $ntp = Get-VMHostService -VMHost $vmhost | Where-Object { $_.Key -eq "ntpd" }
    if (-not $WhatIf) {
        Set-VMHostService -HostService $ntp -Policy "On"
        Start-VMHostService -HostService $ntp -Confirm:$false -ErrorAction SilentlyContinue
    }
    Write-Host "  [+] NTP activé" -ForegroundColor Green
    
    # --- 2. Lockdown Mode ---
    Write-Host "`n[2/8] Configuration Lockdown Mode..." -ForegroundColor Yellow
    $lockdownMgr = Get-View $vmhost.ExtensionData.ConfigManager.HostAccessManager
    $targetMode = if ($StrictLockdown) { "lockdownStrict" } else { "lockdownNormal" }
    if ($lockdownMgr.LockdownMode -eq "lockdownDisabled") {
        if (-not $WhatIf) { $lockdownMgr.ChangeLockdownMode($targetMode) }
        Write-Host "  [+] Lockdown Mode activé: $targetMode" -ForegroundColor Green
        $totalChanges++
    }
    
    # --- 3. Paramètres avancés de sécurité ---
    Write-Host "`n[3/8] Paramètres avancés de sécurité..." -ForegroundColor Yellow
    $advancedSettings = @{
        "UserVars.ESXiShellTimeOut" = 900
        "UserVars.ESXiShellInteractiveTimeOut" = 900
        "UserVars.ESXiVPsDisabledProtocols" = "sslv3,tlsv1,tlsv1.1"
        "Security.AccountLockFailures" = 5
        "Security.AccountUnlockTime" = 900
        "Security.PasswordHistory" = 5
        "Config.HostAgent.log.level" = "info"
        "UserVars.SuppressShellWarning" = 0
        "UserVars.SuppressHyperthreadWarning" = 0
        "Mem.ShareForceSalting" = 2
        "Net.BlockGuestBPDU" = 1
    }
    
    foreach ($setting in $advancedSettings.GetEnumerator()) {
        $current = Get-AdvancedSetting -Entity $vmhost -Name $setting.Key -ErrorAction SilentlyContinue
        if ($current -and $current.Value -ne $setting.Value) {
            if (-not $WhatIf) { 
                Set-AdvancedSetting -AdvancedSetting $current -Value $setting.Value -Confirm:$false 
            }
            Write-Host "  [+] $($setting.Key): $($current.Value) -> $($setting.Value)" -ForegroundColor Green
            $totalChanges++
        }
    }
    
    # --- 4. Syslog ---
    Write-Host "`n[4/8] Configuration Syslog..." -ForegroundColor Yellow
    if (-not $WhatIf) {
        Set-VMHostSysLogServer -VMHost $vmhost -SysLogServer $SyslogServer -ErrorAction SilentlyContinue
        $fwSyslog = Get-VMHostFirewallException -VMHost $vmhost -Name "syslog"
        Set-VMHostFirewallException -Exception $fwSyslog -Enabled $true
    }
    Write-Host "  [+] Syslog -> $SyslogServer" -ForegroundColor Green
    
    # --- 5. Politique de sécurité vSwitch ---
    Write-Host "`n[5/8] Sécurisation vSwitch..." -ForegroundColor Yellow
    Get-VirtualSwitch -VMHost $vmhost | ForEach-Object {
        $policy = Get-SecurityPolicy -VirtualSwitch $_
        if ($policy.AllowPromiscuous -or $policy.ForgedTransmits -or $policy.MacChanges) {
            if (-not $WhatIf) {
                Set-SecurityPolicy -VirtualPortGroup $_ `
                    -AllowPromiscuous $false -ForgedTransmits $false -MacChanges $false `
                    -ErrorAction SilentlyContinue
            }
            Write-Host "  [+] vSwitch $($_.Name): promiscuous/forged/mac désactivés" -ForegroundColor Green
            $totalChanges++
        }
    }
    
    # --- 6. Bannière d'avertissement ---
    Write-Host "`n[6/8] Bannière légale..." -ForegroundColor Yellow
    $banner = "AVERTISSEMENT: Systeme reserve au personnel autorise. Toute activite est journalisee, surveillee et auditee. Tout acces non autorise est interdit et sera poursuivi conformement a la legislation en vigueur."
    if (-not $WhatIf) {
        Get-AdvancedSetting -Entity $vmhost -Name "Config.Etc.issue" | 
            Set-AdvancedSetting -Value $banner -Confirm:$false
        Get-AdvancedSetting -Entity $vmhost -Name "Annotations.WelcomeMessage" | 
            Set-AdvancedSetting -Value $banner -Confirm:$false -ErrorAction SilentlyContinue
    }
    Write-Host "  [+] Bannière configurée" -ForegroundColor Green
    
    # --- 7. Pare-feu ---
    Write-Host "`n[7/8] Durcissement pare-feu..." -ForegroundColor Yellow
    $disableRules = @("CIMSLP", "CIMHttpServer")
    foreach ($ruleName in $disableRules) {
        $rule = Get-VMHostFirewallException -VMHost $vmhost -Name $ruleName -ErrorAction SilentlyContinue
        if ($rule -and $rule.Enabled) {
            if (-not $WhatIf) { Set-VMHostFirewallException -Exception $rule -Enabled $false }
            Write-Host "  [+] Règle $ruleName désactivée" -ForegroundColor Green
            $totalChanges++
        }
    }
    
    # --- 8. Vérification finale ---
    Write-Host "`n[8/8] Vérification..." -ForegroundColor Yellow
    Write-Host "  Lockdown: $((Get-View $vmhost.ExtensionData.ConfigManager.HostAccessManager).LockdownMode)" -ForegroundColor Gray
    Write-Host "  SSH: $((Get-VMHostService -VMHost $vmhost | Where-Object { $_.Key -eq 'TSM-SSH' }).Running)" -ForegroundColor Gray
    Write-Host "  Syslog: $((Get-VMHostSysLogServer -VMHost $vmhost))" -ForegroundColor Gray
}

Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "Hardening terminé - $totalChanges modifications appliquées" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan

Disconnect-VIServer -Confirm:$false

8.2 Automatisation avec Ansible

Pour les équipes pratiquant l'Infrastructure as Code, Ansible avec la collection community.vmware offre une approche déclarative et idempotente du hardening ESXi. L'avantage d'Ansible sur PowerCLI est la gestion de l'état désiré : le playbook peut être exécuté à répétition sans effet de bord, garantissant que toute dérive de configuration est automatiquement corrigée. Pour plus de détails sur les risques liés à l'IaC, consultez notre article sur l'exploitation d'Infrastructure as Code Terraform.

# ansible-playbook esxi-hardening.yml
---
- name: ESXi Hardening Playbook
  hosts: localhost
  gather_facts: no
  vars:
    vcenter_hostname: "vcenter.domaine.local"
    vcenter_username: "admin@vsphere.local"
    vcenter_password: "{{ vault_vcenter_password }}"
    syslog_server: "ssl://siem.domaine.local:6514"
    ntp_servers:
      - "ntp1.domaine.local"
      - "ntp2.domaine.local"
    esxi_hosts:
      - "esxi01.domaine.local"
      - "esxi02.domaine.local"
      - "esxi03.domaine.local"

  tasks:
    - name: Disable SSH on all ESXi hosts
      community.vmware.vmware_host_service_manager:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ item }}"
        service_name: TSM-SSH
        service_policy: "off"
        state: stopped
        validate_certs: yes
      loop: "{{ esxi_hosts }}"
      tags: services

    - name: Configure Lockdown Mode
      community.vmware.vmware_host_lockdown:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ item }}"
        state: normal
        validate_certs: yes
      loop: "{{ esxi_hosts }}"
      tags: lockdown

    - name: Configure NTP servers
      community.vmware.vmware_host_ntp:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ item }}"
        ntp_servers: "{{ ntp_servers }}"
        state: present
        validate_certs: yes
      loop: "{{ esxi_hosts }}"
      tags: ntp

    - name: Configure Syslog
      community.vmware.vmware_host_config_manager:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ item }}"
        options:
          "Syslog.global.logHost": "{{ syslog_server }}"
        validate_certs: yes
      loop: "{{ esxi_hosts }}"
      tags: syslog

    - name: Configure security advanced settings
      community.vmware.vmware_host_config_manager:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ item }}"
        options:
          "Security.AccountLockFailures": 5
          "Security.AccountUnlockTime": 900
          "Security.PasswordHistory": 5
          "UserVars.ESXiShellTimeOut": 900
          "UserVars.ESXiShellInteractiveTimeOut": 900
          "UserVars.ESXiVPsDisabledProtocols": "sslv3,tlsv1,tlsv1.1"
          "Mem.ShareForceSalting": 2
          "Net.BlockGuestBPDU": 1
        validate_certs: yes
      loop: "{{ esxi_hosts }}"
      tags: security

    - name: Configure vSwitch security policy
      community.vmware.vmware_vswitch:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ item }}"
        switch: "vSwitch0"
        security:
          promiscuous_mode: false
          forged_transmits: false
          mac_changes: false
        validate_certs: yes
      loop: "{{ esxi_hosts }}"
      tags: network

8.3 Détection de drift et compliance continue

Le durcissement initial n'est que la première étape. Sans surveillance continue, la configuration dérive inévitablement : un administrateur active SSH pour un dépannage et oublie de le désactiver, un port group est temporairement configuré en mode promiscuous, un compte local est créé "en attendant". La détection de drift automatisée est indispensable :

# Script de détection de drift - à exécuter via cron/scheduled task
function Get-ESXiComplianceDrift {
    $baseline = @{
        "SSH.Running" = $false
        "Lockdown" = "lockdownNormal"
        "AccountLockFailures" = 5
        "SyslogConfigured" = $true
        "PromiscuousMode" = $false
    }
    
    $drifts = @()
    
    Get-VMHost | ForEach-Object {
        $vmhost = $_
        
        # Check SSH
        $sshRunning = (Get-VMHostService -VMHost $vmhost | 
                       Where-Object { $_.Key -eq "TSM-SSH" }).Running
        if ($sshRunning -ne $baseline["SSH.Running"]) {
            $drifts += [PSCustomObject]@{
                Host = $vmhost.Name
                Setting = "SSH Service"
                Expected = "Stopped"
                Actual = "Running"
                Severity = "CRITICAL"
                Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            }
        }
        
        # Check Lockdown
        $lockdown = (Get-View $vmhost.ExtensionData.ConfigManager.HostAccessManager).LockdownMode
        if ($lockdown -eq "lockdownDisabled") {
            $drifts += [PSCustomObject]@{
                Host = $vmhost.Name
                Setting = "Lockdown Mode"
                Expected = $baseline["Lockdown"]
                Actual = $lockdown
                Severity = "CRITICAL"
                Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            }
        }
        
        # Check Promiscuous Mode
        Get-VirtualSwitch -VMHost $vmhost | ForEach-Object {
            $policy = Get-SecurityPolicy -VirtualSwitch $_
            if ($policy.AllowPromiscuous) {
                $drifts += [PSCustomObject]@{
                    Host = $vmhost.Name
                    Setting = "Promiscuous Mode ($($_.Name))"
                    Expected = "Disabled"
                    Actual = "Enabled"
                    Severity = "HIGH"
                    Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                }
            }
        }
    }
    
    if ($drifts.Count -gt 0) {
        Write-Host "`n[ALERTE] $($drifts.Count) dérives détectées !" -ForegroundColor Red
        $drifts | Format-Table -AutoSize
        
        # Envoyer une alerte par email ou webhook
        # Send-MailMessage -To "soc@domaine.local" -Subject "ESXi Drift Detected" ...
    } else {
        Write-Host "[OK] Aucune dérive détectée." -ForegroundColor Green
    }
    
    return $drifts
}

Get-ESXiComplianceDrift
Cycle de durcissement continu ESXi 1 Audit initial STIG / CIS scan Gap analysis 2 Planification Change management Test environnement 3 Application PowerCLI / Ansible Automatisé 4 Vérification Compliance check Validation résultats 5 Monitoring Drift detection SIEM alertes Boucle de retour : re-audit periodique (trimestriel / post-incident) Outils : PowerCLI | Ansible | vRealize Operations | Runecast | SIEM (Splunk/Elastic/Sentinel)

9. Checklist de durcissement ESXi - 30 points

Cette checklist regroupe les 30 points de contrôle essentiels pour un hardening complet d'ESXi. Chaque point est classé par criticité et aligné sur les référentiels STIG et CIS Benchmark. Utilisez-la comme référence lors de vos audits et déploiements, en complément de notre guide de durcissement VMware ESXi qui couvre des aspects complémentaires.

# Point de contrôle Criticité Référence
1 Désactiver SSH - Service TSM-SSH arrêté, politique "Off" CRITIQUE STIG V-258706
2 Activer Lockdown Mode - Normal minimum, Strict recommandé CRITIQUE STIG V-258707
3 Désactiver SLP - Service slpd arrêté, règle pare-feu CIMSLP off CRITIQUE CVE-2021-21974
4 Appliquer les patches - Dernières mises à jour de sécurité VMware CRITIQUE CIS 1.1
5 Forcer TLS 1.2+ - Désactiver SSLv3, TLS 1.0, TLS 1.1 CRITIQUE STIG V-258714
6 Configurer Syslog distant - TLS vers SIEM centralisé HAUTE STIG V-258716
7 Verrouillage de compte - Max 5 tentatives, unlock 15 min HAUTE STIG V-258708
8 Politique mots de passe - 15 caractères min, 4 classes HAUTE CIS 5.2
9 NTP synchronisé - 2 serveurs NTP minimum, service actif HAUTE STIG V-258710
10 Promiscuous Mode off - Tous les vSwitch et port groups HAUTE CIS 7.1
11 Forged Transmits off - Empêcher l'usurpation MAC HAUTE CIS 7.2
12 MAC Changes off - Empêcher le changement d'adresse MAC HAUTE CIS 7.3
13 Bannière légale - Message d'avertissement SSH et DCUI MOYENNE STIG V-258711
14 Shell Timeout - 900 secondes max pour ESXi Shell et SSH HAUTE STIG V-258709
15 Séparation réseaux - vSwitch dédiés : mgmt, vMotion, stockage, VM HAUTE CIS 7.4
16 Chiffrement vMotion - Opportunistic ou Required HAUTE SCG 6.1
17 iSCSI CHAP mutuel - Authentification bidirectionnelle HAUTE CIS 8.1
18 Certificats d'entreprise - Remplacer les certificats auto-signés MOYENNE CIS 6.1
19 Intégration AD - Authentification centralisée, pas de Domain Admins HAUTE CIS 5.1
20 Rôles RBAC personnalisés - Moindre privilège, pas de Full Admin HAUTE CIS 5.3
21 Mot de passe root unique - Différent par hôte, stocké en coffre PAM CRITIQUE Best Practice
22 Secure Boot VM - Activé sur toutes les VMs EFI MOYENNE SCG 4.1
23 vTPM - Ajouté aux VMs Windows pour Credential Guard MOYENNE SCG 4.2
24 Isolation VM - Copy/paste désactivé, HGFS off, 3D off MOYENNE STIG V-258720
25 VM Encryption - VMs sensibles chiffrées au repos HAUTE SCG 4.3
26 Pare-feu restrictif - Seuls les services nécessaires autorisés HAUTE CIS 7.5
27 Transparent Page Sharing salt - Mem.ShareForceSalting = 2 MOYENNE STIG V-258718
28 BPDU Filter - Net.BlockGuestBPDU = 1 MOYENNE CIS 7.6
29 Suppression comptes locaux - Audit et suppression des comptes non documentés HAUTE CIS 5.4
30 Documentation et rollback - Registre des changements, procédures de retour MOYENNE Best Practice

Priorisation recommandée

Commencez par les points CRITIQUE (1-5, 21) qui adressent les vecteurs d'attaque les plus exploités. Puis attaquez les points HAUTE dans l'ordre : services réseau (6-12, 14-17), authentification (19-20), chiffrement (25-26). Les points MOYENNE renforcent la posture mais ne sont pas des urgences. Un score de conformité supérieur à 85 % sur l'ensemble des 30 points constitue une cible raisonnable pour un premier cycle de hardening.

10. Conclusion et ressources

Le durcissement de VMware ESXi n'est pas un projet ponctuel mais un processus continu qui s'inscrit dans une stratégie globale de défense en profondeur. Les attaques ciblant les hyperviseurs se sophistiquent d'année en année : des ransomwares opportunistes (ESXiArgs) aux APT étatiques (UNC3886, Volt Typhoon), la couche de virtualisation est devenue un objectif stratégique pour les adversaires. Chaque hôte ESXi non durci constitue un risque existentiel pour l'organisation qui l'exploite.

Ce guide a couvert l'ensemble du spectre de sécurisation : du verrouillage des accès (Lockdown Mode, SSH, DCUI) à la protection du réseau virtuel (vSwitch, VLAN, pare-feu), en passant par le stockage (CHAP, Kerberos NFS, chiffrement), la gestion des identités (AD, RBAC, PAM), la sécurité des VMs (Secure Boot, vTPM, VBS, isolation), le monitoring (Syslog, SIEM, détection de drift) et l'automatisation (PowerCLI, Ansible). La checklist de 30 points fournit un cadre structuré pour l'évaluation et l'amélioration continue de votre posture de sécurité.

Trois principes directeurs doivent guider votre approche :

  1. Automatiser tout ce qui peut l'être : le hardening manuel est sujet aux erreurs et aux oublis. Les scripts PowerCLI et playbooks Ansible garantissent la cohérence et la reproductibilité. Intégrez-les dans votre pipeline CI/CD d'infrastructure.
  2. Surveiller en permanence : une configuration durcie qui n'est pas surveillée dérive inévitablement. La détection de drift automatisée, couplée à l'intégration SIEM, est votre filet de sécurité contre la régression.
  3. Tester avant de déployer : chaque mesure de durcissement doit être validée dans un environnement de qualification. Les interactions avec les solutions tierces (sauvegarde, monitoring, orchestration) peuvent être subtiles et ne se manifestent parfois qu'en conditions de charge.

Enfin, n'oubliez pas que le hardening de l'hyperviseur s'inscrit dans un écosystème plus large. La sécurité de vCenter Server, la protection de l'infrastructure physique (iLO/iDRAC, réseau de management OOB), la gestion des sauvegardes et la planification de la reprise après sinistre sont autant de composantes interdépendantes. Pour une vision transversale de la sécurité des environnements de virtualisation, notre comparatif de sécurité des hyperviseurs offre une perspective complémentaire.

Ressources officielles

  • VMware Security Configuration Guide (SCG) : documentation officielle de durcissement pour vSphere 8.x
  • DISA STIG for VMware vSphere 8 : guide d'implémentation technique pour les environnements gouvernementaux
  • CIS Benchmark for VMware ESXi 8 : recommandations Level 1 et Level 2 du Center for Internet Security
  • VMware Security Advisories (VMSA) : bulletins de sécurité et CVE associés aux produits VMware
  • VMware PowerCLI Reference : documentation complète des cmdlets PowerCLI
  • Ansible community.vmware collection : modules Ansible pour l'automatisation VMware

Articles connexes

Besoin d'un audit de sécurité vSphere ?

Nos experts réalisent des audits complets de vos infrastructures de virtualisation VMware : évaluation STIG/CIS, tests d'intrusion hyperviseur, revue de configuration vCenter, et plan de remédiation priorisé.

Besoin d'une expertise en cybersécurité ?

Protégez vos hyperviseurs VMware ESXi contre les cybermenaces

Nos Services