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.
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"
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
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 :
- 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.
- 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.
- 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
- Durcissement VMware ESXi : guide de sécurisation complémentaire
- Proxmox vs VMware vs Hyper-V : comparatif de sécurité
- Anatomie d'un ransomware : kill chain et contre-mesures
- Exploitation Kerberos en environnement Active Directory
- Escalade de privilèges Linux : techniques et durcissement
- ISO 27001 : guide complet de conformité
- Forensique mémoire avec Volatility 3 : guide pratique
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é.