Vous avez un projet ?
Temps de lecture 11 minutes

Un sauvetage de données grâce à vSAN ?

Publié le 7 March 2023
scroll
N’oubliez pas
de partager
cet article

Vous avez sans doute entendu parler de la vague d’attaques Ransomware contre les ESXi.

Ce type d’attaque vient chiffrer tous les fichiers importants sur vos ESXs : les fichiers de configurations de l’ESXi, mais aussi (et surtout) tous les fichiers de vos VMs (.vmx, .vmdk, -flat.vmdk…)

Si vous êtes touchés par une telle attaque, vos VMs sont probablement toutes inaccessibles et il vous est impossible de vous connecter aux ESXi, que ce soit par le client Web, le SSH ou la console… Il faut alors espérer avoir de bonnes sauvegardes…

Ou bien avoir eu la bonne idée de choisir VMware vSAN comme solution de stockage.

En effet, contrairement à toutes les solutions concurrentes – qui stockent les disques des VMs sous forme de fichiers – vSAN stocke les disques des VMs sous forme d’Objets. Les attaques de type Ransomware actuelles viennent chiffrer des fichiers et ne sont, actuellement, pas programmées pour attaquer des objets. Avec un stockage vSAN, tout n’est peut-être pas perdu.

L’un de nos clients a été touché par une telle attaque et avec l’aide du support VMware nous avons pu retrouver une grande partie des données. Nous allons ici détailler les étapes suivies pour retrouver l’accès à ces données.
Nous ne pouvons affirmer que cela fonctionnera dans votre cas et nous vous invitons évidemment à vous rapprocher du Support VMware pour vous accompagner dans ces étapes…

Voici, dans les grandes lignes, les étapes suivies :

Etape 1 : Réinstaller un ESX et tenter de l’intégrer au cluster

Comme indiqué plus haut, il est impossible de se connecter aux ESXi. De plus, par sécurité, le réseau LAN des ESXs a dû être coupé (pour ne pas propager une éventuelle attaque). Il ne reste donc plus que l’accès « Ecran/Clavier »

Nous allons donc choisir un ESXi cobaye du cluster et le redémarrer. Comme les fichiers de configuration sont eux aussi chiffrés, les 2 « Bootbanks » sont corrompues et l’ESXi ne redémarrera pas. Il faut passer par la case « Réinstallation »

L’idée ici est de s’inspirer de la procédure de VMware permettant à un ESX ayant planté de se reconnecter à un cluster vSAN existant :

  1. Commencer par réinstaller l’ESXi en respectant la version déjà présente sur les ESXi
  2. Puis, faire une configuration réseau vSAN minimale.

Les étapes 3, 4 et 5 de la KB sont impossibles dans notre cas :

  1. Le LAN de l’ESX étant coupé, même si le vCenter est encore accessible, nous n’ajouterons pas l’hôte au vCenter
  2. Les ESX du cluster sont tous inaccessible, donc pas de connexion SSH possible et l’étape 5 est donc impossible

Nous en sommes donc à l’étape 6 : rejoindre le cluster par la commande

 

esxcli vsan cluster join -u sub_cluster_UUID

Si vous connaissez ce sub_cluster_id, c’est top.

Sinon, il faut le trouver. Vous pouvez tenter de consulter les logs vmkernels (accessible par la combinaison de touches ALT+F12 tapée en étant connecté sur la console d’un ESX) et de chercher un ID unique visible sur tous les ESXs du cluster…

Après avoir passé la commande sur l’ID que vous pensez être le bon, nous vérifions si l’hôte a réussi à rejoindre le cluster par la commande :

 

esxcli vsan cluster get

Si cela s’est bien passé, vous devriez avoir un résultat semblable à celui-ci (l’hôte est intégré à un cluster à plusieurs membres) :

 

[root@monesx1:~] esxcli vsan cluster get

Cluster Information

   Enabled: true

   Current Local Time: 2023-02-10T11:01:51Z

   Local Node UUID: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Local Node Type: NORMAL

   Local Node State: MASTER

   Local Node Health State: HEALTHY

   Sub-Cluster Master UUID: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Sub-Cluster Backup UUID: 63dd24fb-f098-7dd8-d108-78ac440739b8

   Sub-Cluster UUID: 5229207b-c00a-242f-3e79-ac063a9c26fb

   Sub-Cluster Membership Entry Revision: 1

   Sub-Cluster Member Count: 4

   Sub-Cluster Member UUIDs: 63dd24fb-f098-7dd8-d108-78ac440739b8, 63dd24b1-d4ae-9a6e-2d27-78ac44072152, 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76, 63dd126c-6aca-ebf8-a3be-78ac44073886

   Sub-Cluster Member HostNames: monesx4, monesx3, monesx1, monesx2

   Sub-Cluster Membership UUID: 9bc1de63-6484-6576-c270-78ac4406ef76

   Unicast Mode Enabled: true

   Maintenance Mode State: OFF

   Config Generation: cccca5b8-cf79-4ff3-a108-432b6fc0a371 7 2023-02-05T08:53:21.872

   Mode: REGULAR

Vous pouvez passer à l’Etape 3. S’il n’y a qu’un seul membre, nous continuons par l’étape 2.

Etape 2 : Reconstruire le Cluster

Si vous êtes ici, c’est que l’ID n’était pas le bon. L’hôte se retrouve tout seul dans un cluster et la liste des « voisins » Unicast est probablement vide :

 

[root@monesx1:~] esxcli vsan cluster get

Cluster Information

   Enabled: true

   Current Local Time: 2023-02-10T11:01:51Z

   Local Node UUID: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Local Node Type: NORMAL

   Local Node State: MASTER

   Local Node Health State: HEALTHY

   Sub-Cluster Master UUID: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Sub-Cluster Backup UUID:

   Sub-Cluster UUID: 5229207b-c00a-242f-3e79-ac063a9c26fb

   Sub-Cluster Membership Entry Revision: 0

   Sub-Cluster Member Count: 1

   Sub-Cluster Member UUIDs: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Sub-Cluster Member HostNames: monesx1

   Sub-Cluster Membership UUID: 9bc1de63-6484-6576-c270-78ac4406ef76

   Unicast Mode Enabled: true

   Maintenance Mode State: OFF

   Config Generation: None 0 0.0

  Mode: REGULAR


[root@monesx1:~] esxcli vsan cluster unicastagent list

[root@monesx1:~]

Nous allons maintenant vérifier si l’hôte réussi à « voir » qu’il possède des disques « taggués » vSAN :

 

[root@monesx1:~] esxcli vsan debug disk list | grep -i cmmds

   In Cmmds: true

   In Cmmds: true

   In Cmmds: true

   In Cmmds: true

   In Cmmds: true

Dans mon cas, j’ai bien mes 5 disques (1 disque de cache et 4 disques capacitifs). C’est positif, nous avançons. Nous vérifions maintenant qu’il détecte bien les objets vSAN :

 

[root@monesx1:~] esxcli vsan debug object health summary get

Health Status                                              Number Of Objects

---------------------------------------------------------  -----------------

remoteAccessible                                                           0

inaccessible                                                             161

reduced-availability-with-no-rebuild                                       0

reduced-availability-with-no-rebuild-delay-timer                           0

reducedavailabilitywithpolicypending                                       0

reducedavailabilitywithpolicypendingfailed                                 0

reduced-availability-with-active-rebuild                                   0

reducedavailabilitywithpausedrebuild                                       0

data-move                                                                  0

nonavailability-related-reconfig                                           0

nonavailabilityrelatedincompliancewithpolicypending                        0

nonavailabilityrelatedincompliancewithpolicypendingfailed                  0

nonavailability-related-incompliance                                       0

nonavailabilityrelatedincompliancewithpausedrebuild                        0

healthy                                                                    0

Les objets sont présents mais ils sont inaccessibles. C’est attendu, puisque l’hôte est seul membre du cluster. Nous pouvons continuer à avancer.

Il faut maintenant réinstaller, un à un, les autres membres du cluster, et donc, comme pour le premier ESX :

  1. Réinstaller l’ESX à la même version
  2. Appliquer une configuration réseau vSAN minimale

Une fois les autres membres du cluster réinstallés, nous allons les ajouter au cluster créé par notre premier ESX en exécutant la commande : esxcli vsan cluster join -u sub_cluster_UUID (l’UUID à utiliser ici est le même que celui utilisé pour le premier ESX)

Puis, nous recréons les « voisins » unicast en s’aidant de la KB VMware 2150303 et en respectant le fait qu’un hôte ne doit pas être voisin de lui-même :

  • L’hôte 1 doit avoir les hôtes 2, 3 et 4 dans sa liste
  • L’hôte 2 doit avoir les hôtes 1, 3 et 4 dans sa liste

C’est la commande :

 

esxcli vsan cluster unicastagent add -t node -u <Host_UUID> -U true -a <Host_VSAN_IP> -p 12321

qui permet de recréer cette liste.

Si tout s’est bien passé, vous devriez avoir les 4 hôtes membres d’un seul et même cluster. Et les objets doivent maintenant être listés comme « Healthy »

 

[root@monesx1:~] esxcli vsan cluster get

Cluster Information

   Enabled: true

   Current Local Time: 2023-02-10T11:01:51Z

   Local Node UUID: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Local Node Type: NORMAL

   Local Node State: MASTER

   Local Node Health State: HEALTHY

   Sub-Cluster Master UUID: 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76

   Sub-Cluster Backup UUID: 63dd24fb-f098-7dd8-d108-78ac440739b8

   Sub-Cluster UUID: 5229207b-c00a-242f-3e79-ac063a9c26fb

   Sub-Cluster Membership Entry Revision: 1

   Sub-Cluster Member Count: 4

   Sub-Cluster Member UUIDs: 63dd24fb-f098-7dd8-d108-78ac440739b8, 63dd24b1-d4ae-9a6e-2d27-78ac44072152, 63dd0bfc-b2d1-ff74-f1f7-78ac4406ef76, 63dd126c-6aca-ebf8-a3be-78ac44073886

   Sub-Cluster Member HostNames: monesx4, monesx3, monesx1, monesx2


Sub-Cluster Membership UUID: 9bc1de63-6484-6576-c270-78ac4406ef76

   Unicast Mode Enabled: true

   Maintenance Mode State: OFF

   Config Generation: cccca5b8-cf79-4ff3-a108-432b6fc0a371 7 2023-02-05T08:53:21.872

   Mode: REGULAR




[root@monesx1:~] esxcli vsan debug object health summary get

Health Status                                              Number Of Objects

---------------------------------------------------------  -----------------

remoteAccessible                                                           0

inaccessible                                                               0

reduced-availability-with-no-rebuild                                       0

reduced-availability-with-no-rebuild-delay-timer                           0

reducedavailabilitywithpolicypending                                       0

reducedavailabilitywithpolicypendingfailed                                 0

reduced-availability-with-active-rebuild                                   0

reducedavailabilitywithpausedrebuild                                       0

data-move                                                                  0

nonavailability-related-reconfig                                           0

nonavailabilityrelatedincompliancewithpolicypending                        0

nonavailabilityrelatedincompliancewithpolicypendingfailed                  0

nonavailability-related-incompliance                                       0

nonavailabilityrelatedincompliancewithpausedrebuild                        0

healthy     

Etape 3 : Constater les dégâts

Lorsque le cluster est reconstitué et que les objets sont sains, il est temps d’aller voir l’état des VMs :

[root@monesx1:~] ls -l /vmfs/volumes/vsan:5229207bc00a242f-3e79ac063a9c26fb/MA-VM4/

total 159784

-rw-r--r--    1 root     root           624 Dec 26 14:45 MA-VM4-2dd32c7d.hlog.royal_u

-rw-------    1 root     root           544 Dec 26 14:45 MA-VM4-aux.xml.royal_u

-rw-------    1 root     root       4916240 Dec 26 14:45 MA-VM4-ctk.vmdk.royal_u

-rw-------    1 root     root          9216 Dec 26 14:45 MA-VM4.nvram.royal_u

-rw-------    1 root     root          1216 Dec 26 14:45 MA-VM4.vmdk.royal_u

-rw-r--r--    1 root     root           576 Dec 26 14:45 MA-VM4.vmsd.royal_u

-rwxr-xr-x    1 root     root          4368 Dec 26 14:45 MA-VM4.vmx.royal_u

-rw-------    1 root     root          4464 Dec 26 14:45 MA-VM4.vmxf.royal_u

-rw-r--r--    1 root     root          1473 Feb  2 15:45 readme

-rw-r--r--    1 root     root       3386384 Dec 26 14:45 vmware-19.log.royal_u

-rw-r--r--    1 root     root      11416208 Dec 26 14:45 vmware-20.log.royal_u

-rw-r--r--    1 root     root      14268976 Dec 26 14:45 vmware-21.log.royal_u

-rw-r--r--    1 root     root        287392 Dec 26 14:45 vmware-22.log.royal_u

-rw-r--r--    1 root     root       8368448 Dec 26 14:45 vmware-23.log.royal_u

-rw-r--r--    1 root     root       5305280 Dec 26 14:45 vmware-24.log.royal_u

-rw-r--r--    1 root     root      20798720 Dec 26 14:45 vmware.log.royal_u

-rw-------    1 root     root      89129488 Dec 26 14:45 vmx-MA-VM4-585bd2db439e8e507d7ef699dd2c2e4e8cf8e074-1.vswp.royal_u

 

Tous les fichiers ont une extension « .royal_u »… Nous sommes victimes de Royal Ransomware. Chaque dossier contien maintenant aussi un fichier readme contenant les instructions de rançons :

 

Malheureusement, il n’existe pas encore d’outils de déchiffrement pour ce Ransomware… Donc nous continuons avec vSAN.

A ce stade, il est plus aisé de travailler en SSH, voire avec un vCenter. Nous allons donc activer le LAN des ESXs. Si le premier « join cluster » de l’étape 1 a été concluant, alors certains ESXs membres du cluster n’ont pas été réinstallés et peuvent potentiellement toujours être infectés. Il est alors plus prudent de tous les réinstaller afin d’effacer toute trace du virus.

Etape 4 : Retrouver le contenu des disques

Comme on l’a vu juste au-dessus, le fichier descripteur du disque (.vmdk) est chiffré. Il est n’est donc pas accessible. Nous avons donc besoin de le recréer. Mais on a besoin de quelques infos pour cela.

Identifier les objets vSAN Accessible mais non associés

Si vous ne souhaitez pas réinstaller un vCenter, vous pouvez utiliser la commande esxcli vsan debug object list –all pour remonter les informations nécessaires. Cependant, vCenter offre l’accès a rvc et facilite l’identification des objets à récupérer.

Ainsi, de mon côté, j’ai préféré réinstaller un vCenter en dehors de vSAN. J’ai créé un nouveau cluster avec vSAN activé et j’ai intégré mes 4 nœuds. Je peux donc utiliser les commandes rvc pour continuer le debug. Et je me suis donc aidé de la KB VMware permettant d’identifier les objets non associés.

 

#La commande suivante fait un rapport de tous les objets et liste donc tous les objets « Unassociated »

> vsan.obj_status_report -t <pathToCluster>

2023-02-04 10:53:13 +0000: Querying all VMs on vSAN ...

2023-02-04 10:53:13 +0000: Querying DOM_OBJECT in the system from monesx1 ...

2023-02-04 10:53:13 +0000: Querying DOM_OBJECT in the system from monesx2 ...

2023-02-04 10:53:13 +0000: Querying DOM_OBJECT in the system from monesx3 ...

2023-02-04 10:53:13 +0000: Querying DOM_OBJECT in the system from monesx4 ...




[...]




+--------------------------------------------+---------+----------+

| Unassociated objects                       | 37      |          |

|    [...]                                   |         |          |

|    cf8dd75f-cc5e-6139-3851-78ac440739b8    |         | 3/3      |

|    19e3d95f-06c7-3a55-42cd-78ac44073886    |         | 3/3      |

|    [...]                                   |         |          |

+--------------------------------------------+---------+----------+

L’idée est ensuite de copier toutes les lignes contenant les UUID non associés et de créer un nouveau fichier « input.txt » puis de lancer une commande permettant de ne garder que ces UUID.

root@vcenter [ /tmp ]# cat /tmp/input.txt | awk '{print $2}'  |awk '/^'.'/ {printf "%s ",$0} END {print ""}' > /tmp/output.txt

Le fichier output.txt contient alors tous les objets non associés. Il nous faut maintenant les identifier. Pour cela, nous retournons sur rvc et nous passons cette liste en paramètre de la commande vsan.object_info. (ici, je me limite aux 2 objets pris en exemple, mais il est tout à fait possible de passer tous les UUID des objets remontés comme non associés par la commande précédente) :

> vsan.object_info localhost/DC/computers/vSAN/ cf8dd75f-cc5e-6139-3851-78ac440739b8 19e3d95f-06c7-3a55-42cd-78ac44073886

Je vous conseille alors de mettre le résultat de cette commande dans un fichier texte que vous conserverez précieusement. Ce fichier contient toutes les informations nécessaires vous permettant de retrouver l’accès aux disques de vos VMs. Voici un extrait de son contenu :

[...]

DOM Object: cf8dd75f-cc5e-6139-3851-78ac440739b8 (v15, owner: monesx1.virtu.local, proxy owner: None, policy: stripeWidth = 1, cacheReservation = 0, proportionalCapacity = [0, 100], hostFailuresToTolerate = 1, forceProvisioning = 0, spbmProfileId = 4daa9a65-6716-4c5d-88ea-23a0d6f5b6e3, spbmProfileGenerationNumber = 0, objectVersion = 15, replicaPreference = Performance, iopsLimit = 0, checksumDisabled = 0, CSN = 20994, SCSN = 20919, spbmProfileName = vSAN - Raid1)

  RAID_1

    Component: dd65df63-247a-5c5c-12bb-78ac440739b8 (state: ACTIVE (5), host: monesx3.virtu.local, capacity: naa.500a075129964464, cache: naa.58ce38ee210f0705, votes: 1, usage: 1.0 GB, proxy component: false)

    Component: cf9adf63-4c7a-69f3-1eac-78ac440739b8 (state: ACTIVE (5), host: monesx2.virtu.local, capacity: naa.500a075129964490, cache: naa.58ce38ee2100fa85, votes: 1, usage: 1.0 GB, proxy component: false)

  Witness: e2d0de63-3811-94b1-137f-78ac440739b8 (state: ACTIVE (5), host: monesx1.virtu.local, capacity: naa.500a075129963822, cache: naa.58ce38ee210f06f1, votes: 1, usage: 0.0 GB, proxy component: false)

  Extended attributes:

    Address space: 273804165120B (255.00 GB)

    Object class: vmnamespace

    Object path: /vmfs/volumes/vsan:5229207bc00a242f-3e79ac063a9c26fb/MA-VM4

    Object capabilities: NONE




DOM Object: 19e3d95f-06c7-3a55-42cd-78ac44073886 (v15, owner: monesx1.virtu.local, proxy owner: None, policy: stripeWidth = 1, cacheReservation = 0, proportionalCapacity = 0, hostFailuresToTolerate = 1, forceProvisioning = 0, spbmProfileId = 4daa9a65-6716-4c5d-88ea-23a0d6f5b6e3, spbmProfileGenerationNumber = 0, objectVersion = 15, replicaPreference = Performance, iopsLimit = 0, checksumDisabled = 0, CSN = 21247, SCSN = 21188, spbmProfileName = vSAN - Raid1)

  RAID_1

    Component: 5cd1df63-5617-16d5-ef1c-78ac4406ef76 (state: ACTIVE (5), host: monesx3.virtu.local, capacity: naa.500a075129964107, cache: naa.58ce38ee210f0705, votes: 1, usage: 60.0 GB, proxy component: false)

    Component: bfd8df63-dc23-b8d8-bffd-78ac4406ef76 (state: ACTIVE (5), host: monesx4.virtu.local, capacity: naa.500a0751299641e7, cache: naa.58ce38ee210efa11, votes: 1, usage: 60.0 GB, proxy component: false)

  Witness: 5cd1df63-b85b-18d5-4891-78ac4406ef76 (state: ACTIVE (5), host: monesx1.virtu.local, capacity: naa.500a075129964230, cache: naa.58ce38ee210f06f1, votes: 1, usage: 0.0 GB, proxy component: false)

  Extended attributes:

    Address space: 161061273600B (150.00 GB)

    Object class: vdisk

    Object path: /vmfs/volumes/vsan:5229207bc00a242f-3e79ac063a9c26fb/cf8dd75f-cc5e-6139-3851-78ac440739b8/MA-VM4.vmdk

    Object capabilities: NONE

[...]

Il y a deux types d’objets remontés par cette dernière commande :

  • Les objets de type Namespace à C’est le « dossier » contenant les fichiers de la VM
  • Les objets de type vDisk à C’est le disque de la VM

Pour ces 2 types d’objets, on identifie facilement la VM concernée en lisant la ligne Object Path.

Dans notre cas, nous souhaitons retrouver l’accès aux disques. Nous allons donc travailler uniquement sur les objets vDisk et nous notons les informations suivantes :

  • UUID de l’objet : Dans mon cas 19e3d95f-06c7-3a55-42cd-78ac44073886
  • Taille du disque : Dans mon cas 150.00 GB

Créer un nouveau disque

Je vous conseille ici de créer une nouvelle VM vierge sur laquelle vous remonterez les disques récupérés. Cela évitera de démarrer une VM potentiellement infectée.

Dans cette étape, nous créons un nouveau disque d’une taille identique au disque source (ici, 150Go) puis nous modifions le descripteur pour pointer vers l’objet vSAN repéré à l’étape précédente.

En effet, dans le fichier descripteur du nouveau disque (.vmdk), la partie « Extent description » indique l’UUID de l’objet concerné par le descripteur. Nous modifions ainsi la ligne pour indiquer l’emplacement de l’objet du disque que nous voulons récupérer :

#Avant Modification : 

[root@monesx01:/vmfs/volumes/vsan:523011e791d2eabf-6a83d7de246fbb48/b5b5eb63-1a84-cd91-5f17-0050568287d1] cat Recup-VM_1.vmdk

[...]




# Extent description

RW 314572800 VMFS "vsan://5229207bc00a242f-3e79ac063a9c26fb/c7b5eb63-d70a-5ee6-dd6f-0050568287d1"




[...]




#Après modification :

[root@monesx01:/vmfs/volumes/vsan:523011e791d2eabf-6a83d7de246fbb48/b5b5eb63-1a84-cd91-5f17-0050568287d1] cat Recup-VM_1.vmdk

[...]




# Extent description

RW 314572800 VMFS "vsan://5229207bc00a242f-3e79ac063a9c26fb/19e3d95f-06c7-3a55-42cd-78ac44073886"

[...]

Il ne reste plus qu’à « Recharger » la VM :

 

[root@monesx01:~] vim-cmd vmsvc/getallvms

Vmid     Name                                   File                                         Guest OS          Version   Annotation

1      Recup-VM   [vsanDatastore] b5b5eb63-1a84-cd91-5f17-0050568287d1/Recup-VM.vmx   windows2019srv_64Guest   vmx-19

[root@monesx01:~] vim-cmd vmsvc/reload 1

Et à contrôler dans la VM si les données sont accessibles :

Verification des données

Conclusion

Cet article décrit la procédure à suivre pour retrouver l’accès aux données contenues dans vSAN avant l’attaque. En revanche, si les VMs avaient aussi été chiffrées au niveau OS, alors les données ne seront malheureusement pas accessibles. Et alors, de bonnes sauvegardes et une bonne solution de PRA sera la seule protection à ce type d’attaque.

Par ailleurs, il est important de noter qu’en modifiant le descripteur des disques créés temporairement, vous rendrez l’objet « vdisk » temporaire associé « Non associés » du point de vue vSAN. Ainsi, une fois la donnée remontée, nous vous conseillons de la sortir de vSAN (par une sauvegarde et/ou un Storage vMotion) afin de pouvoir re-créer proprement le cluster vSAN lorsque les opérations de récupérations seront terminées.

Enfin, encore une fois, cette procédure a fonctionné dans notre cas mais nous ne pouvons pas garantir que cela fonctionnera pour votre cas. Et nous vous invitons évidemment à contacter Metanext et/ou le support VMware pour vous accompagner dans toutes ces démarches.

Aurélien de Beauchesne