ZFS Readonly : l’astuce anti-ransomware que vous pouvez déployer aujourd’hui

Cet article vous a aidé ?

Le ransomware ne « pirate » généralement pas le stockage. Il exploite le fait que votre stockage fait exactement ce qu’on lui demande : accepter des écritures d’une identité de confiance devenue soudainement peu fiable. Votre serveur de fichiers ne sait pas faire la différence entre un comptable sauvegardant un tableur et un logiciel malveillant chiffrant 4 millions de documents à pleine vitesse. Pour le disque, ce n’est que de l’écriture enthousiaste.

ZFS vous donne un levier apparemment simple : les jeux de données en lecture seule. Combiné aux snapshots et à la réplication, il vous permet de placer des parties de votre stockage dans une posture où le ransomware ne peut pas chiffrer ce qu’il ne peut pas écrire. Ce n’est pas une panacée — rien ne l’est — mais c’est un contrôle que vous pouvez déployer aujourd’hui, avec des commandes que vous pouvez exécuter en production sans rien acheter ni réorganiser toute votre architecture.

Ce que readonly signifie réellement (et ce que ce n’est pas)

La propriété ZFS readonly est exactement ce que son nom indique : elle ordonne à ZFS de monter un dataset en mode lecture seule. Lorsqu’elle est définie, les écritures via ce point de montage doivent échouer. C’est puissant, mais ce n’est pas magique. C’est une politique appliquée au niveau du stockage sur un dataset, pas un jugement moral sur l’intention.

Readonly s’applique au dataset, pas à vos intentions

Quand vous définissez readonly=on sur un dataset :

  • Les écritures via le système de fichiers monté sont bloquées (les applications verront des erreurs comme « Read-only file system »).
  • Les mises à jour de métadonnées nécessitant des écritures (création de fichiers, renommages, chmod, etc.) échouent aussi.
  • Vous pouvez toujours lire, parcourir et calculer des sommes de contrôle ; ZFS est heureux de fournir les données.

Ce que cela ne veut pas dire :

  • Cela ne protège pas automatiquement les snapshots. Les snapshots ont leur propre histoire de sécurité.
  • Cela n’empêche pas un utilisateur privilégié de le remettre en off.
  • Cela ne vous protège pas d’une destruction au niveau du pool (par exemple, zpool destroy par root). C’est pourquoi la séparation des responsabilités est importante.
  • Cela ne bloque pas les écritures via un autre chemin qui contourne le système de fichiers monté (par exemple, si vous répliquez un dataset dans ce dernier, vous pouvez écrire au niveau ZFS, pas via le montage POSIX).

En d’autres termes : readonly est une ceinture de sécurité solide, pas un téléporteur. Il vous aide à survivre à des chocs courants, mais vous ne devriez pas non plus foncer dans un mur.

Ce que le ransomware fait typiquement à vos fichiers

Le ransomware au niveau fichier :

  • Parcourt les répertoires, souvent via les API standard, parfois en multithreading.
  • Lit un fichier, écrit une version chiffrée (en place ou côte à côte), puis renomme.
  • Supprime les originaux ou les tronque.
  • Cible les serveurs de fichiers via SMB/NFS parce qu’ils concentrent des données partagées et sont souvent largement accessibles en écriture.

Si le dataset sous-jacent est en lecture seule, ces écritures, ces truncations, ces renommages et ces suppressions échouent. Le malware peut toujours lire vos données (la confidentialité est un contrôle séparé), mais il ne peut pas chiffrer votre dataset en place. C’est une énorme différence quand vous essayez de maintenir l’activité.

Une plaisanterie, parce qu’on l’a bien méritée : readonly, c’est comme mettre vos données derrière une vitre — on peut toujours les admirer, mais on ne peut pas leur faire un « coup de peinture » ransomware.

Pourquoi le mode readonly fonctionne contre les ransomwares

La plupart des recommandations anti-ransomware se concentrent sur la détection, le contrôle des endpoints et les sauvegardes. Tout cela est bon. Mais la vérité opérationnelle est : le ransomware n’a pas besoin d’être intelligent si votre stockage est grande ouvert. L’immuabilité au niveau stockage change la donne en rendant l’étape « chiffrer et écraser » impossible (ou au moins beaucoup plus difficile).

Readonly réduit votre rayon d’impact

En production, les données sont rarement homogènes. Vous avez :

  • Des ensembles de travail actifs (nécessitent des écritures fréquentes).
  • Des données de référence (rarement modifiées, fortement lues).
  • Des archives (ne devraient jamais changer).
  • Des cibles de sauvegarde/réplica (devraient être en écriture-une-fois en pratique).

Readonly convient parfaitement aux données de référence, aux archives et aux cibles de réplica. Si un ransomware frappe un poste de travail ou un compte serveur avec un large accès, il ne peut endommager que les datasets réellement modifiables.

Readonly est immédiat, peu coûteux et observable

Les contrôles de sécurité qui demandent un long projet tendent à céder face aux « priorités business urgentes ». ZFS readonly n’est pas un de ces contrôles. Vous pouvez :

  • L’activer par un simple changement de propriété.
  • Le confirmer avec zfs get et par le comportement réel des applications.
  • Surveiller les tentatives d’écriture (les applications vont journaliser des erreurs ; les clients SMB/NFS vont se plaindre).

Cette observabilité compte. Dans plusieurs incidents que j’ai vus se dérouler, le premier indice solide était « pourquoi ce répertoire est-il soudainement en lecture seule ? ». Il n’était pas en lecture seule : le système essayait d’écrire des données corrompues à grande vitesse et heurtait des garde-fous. Ces garde-fous ont transformé une catastrophe en une nuisance bruyante.

Readonly se marie bien avec les snapshots — et ce sont les snapshots que vous utiliserez réellement

Readonly est un contrôle préventif. Les snapshots sont votre contrôle de récupération. Ensemble, ils vous permettent de dire :

  • « Ce dataset n’est pas censé changer. » (readonly)
  • « Si quelque chose change alors que ça ne devrait pas, je peux revenir en arrière ou restaurer rapidement. » (snapshots + réplication)

Si vous ne faites que des snapshots, le ransomware peut quand même chiffrer le système de fichiers actif et vous serez en mode restauration. Si vous ne faites que readonly, vous pourriez bloquer des modifications légitimes. L’équilibre consiste à concevoir votre agencement de datasets pour être strict là où c’est sûr et flexible là où c’est nécessaire.

Faits intéressants et contexte historique

L’ingénierie du stockage a une longue mémoire. Quelques points de contexte qui font que ZFS readonly ressemble moins à une astuce et plus à la forme moderne d’idées anciennes :

  1. ZFS a commencé au début des années 2000 chez Sun Microsystems, construit autour de l’idée que le système de fichiers et le gestionnaire de volumes devraient être un même système, pas deux colocataires mal assortis.
  2. Copy-on-write (CoW) est la superpuissance de ZFS : les données ne sont pas écrasées in situ ; de nouveaux blocs sont écrits et les pointeurs sont mis à jour. Cela rend les snapshots peu coûteux et cohérents.
  3. Les snapshots précèdent le ransomware en tant que menace grand public. Ils ont été conçus pour les erreurs d’administration et la cohérence, mais ils se prêtent parfaitement à la récupération par rollback.
  4. « Immutabilité » n’est pas nouvelle : les stockages WORM (write once, read many) existent depuis des décennies pour des archives de conformité. ZFS readonly en est une approximation pratique pour de nombreux datasets.
  5. Le ransomware moderne a évolué depuis les « screen lockers » vers l’extorsion par chiffrement quand la cryptographie est devenue plus facile à opérationnaliser et que les sauvegardes se sont généralisées.
  6. Les partages SMB sont devenus des cibles de grande valeur parce qu’ils concentrent les données partagées et héritent souvent de permissions larges : un utilisateur compromis peut toucher beaucoup.
  7. Les premiers adoptants de ZFS ont appris à la dure que « les snapshots existent » n’est pas la même chose que « les snapshots sont sûrs ». Si un attaquant peut détruire les snapshots, vous revenez au point de départ.
  8. La séparation opérationnelle des tâches est plus ancienne que les ordinateurs : la personne qui approuve les dépenses ne devrait pas être celle qui peut transférer les fonds. La même logique s’applique à qui peut supprimer des snapshots ou changer readonly.
  9. « Sauvegardes hors ligne » signifiait autrefois des bandes. Aujourd’hui cela signifie souvent « une réplique que l’on ne peut pas modifier depuis le plan d’identités de production ». Les datasets readonly sont une pièce de ce puzzle.

Deuxième plaisanterie (et la dernière) : le ransomware est la seule charge de travail que j’ai vue évoluer parfaitement sans évaluation de performance.

Patrons de conception : où readonly s’intègre dans le stockage réel

Readonly est plus efficace quand vos datasets reflètent la réalité : ce qui change, ce qui ne devrait pas, et ce qui doit être récupérable rapidement. Vous ne saupoudrez pas readonly comme un assaisonnement ; vous construisez des frontières.

Patron 1 : séparer les données « actives » et les données « publiées »

Commun dans l’analytics et les pipelines de contenu :

  • Dataset d’ingestion actif : inscriptible, utilisé par des jobs ETL ou des uploads.
  • Dataset publié : readonly, utilisé par des lecteurs (outils BI, serveurs web, équipes en aval).

La promotion est une action contrôlée : un snapshot ou un clone est déplacé dans l’espace de noms publié, puis verrouillé en lecture seule. Si un ransomware frappe un nœud d’ingestion, il peut détruire l’ingestion, mais le publié reste intact.

Patron 2 : réplicas readonly comme « air gap du pauvre »

Configurez un hôte backup/DR qui reçoit la réplication ZFS. Côté cible, gardez les datasets montés en readonly (ou pas montés du tout) et restreignez qui peut changer les propriétés. La cible devient « en ligne mais pas facilement inscriptible », ce qui est souvent le compromis opérationnel idéal.

La clé est la séparation d’identité : les systèmes de production ne devraient pas avoir des identifiants capables de réécrire la cible de sauvegarde au-delà de la capacité étroite de réplication. Si la même clé SSH root peut administrer les deux côtés, vous avez construit un mécanisme d’autodestruction à grande vitesse.

Patron 3 : répertoires personnels immuables (avec prudence)

Pour certains environnements — kiosques, laboratoires, centres d’appel — les données utilisateurs ne doivent pas persister ou changer en dehors d’une synchronisation contrôlée. Vous pouvez monter des home directories à partir d’un dataset readonly et superposer une couche écrivable ailleurs. Cela bloque une catégorie entière d’attaques « chiffrer tout ce que je vois ».

Mais soyez honnête : pour les knowledge workers, les home directories sont des données actives. Ne transformez pas readonly en attaque par déni de productivité.

Patron 4 : protégez vos restaurations « known-good »

La plupart des organisations ont un répertoire comme /srv/releases, /srv/installers, /srv/golden, ou « la chose dont on réinstalle quand le monde s’effondre ». Faites-en un dataset séparé. Mettez-le en readonly. Snapshottez-le. Répliquez-le. Si un ransomware frappe et que vous ne pouvez pas réinstaller en toute sécurité, vous découvrirez de nouvelles définitions de « mauvaise journée ».

Vérification du modèle de menace

Readonly aide surtout contre :

  • Comptes utilisateurs compromis ayant accès aux partages de fichiers.
  • Malware s’exécutant sur des serveurs applicatifs qui écrivent sur des datasets partagés.
  • Scripts destructeurs accidentels (oui, ça compte).

Readonly aide moins contre :

  • Compromission root sur le serveur de stockage lui-même.
  • Attaquants disposant de droits administratifs ZFS qui peuvent basculer les propriétés ou détruire des snapshots.
  • Accès physique et manipulation malveillante au niveau noyau.

Ce n’est pas une raison pour l’ignorer. C’est une raison de le coupler avec la séparation des rôles, la protection des snapshots et une cible de réplication qui n’est pas gouvernée par le même ensemble de clés.

Tâches pratiques (commandes + interprétation)

Toutes les commandes ci-dessous supposent OpenZFS sur Linux avec un pool typique nommé tank. Adaptez les noms à votre environnement. L’important n’est pas la chaîne exacte, mais l’intention opérationnelle et l’apparence du « bon ».

Tâche 1 : inventorier les datasets et repérer les candidats évidents pour readonly

cr0x@server:~$ sudo zfs list -o name,used,avail,refer,mountpoint
NAME                 USED  AVAIL  REFER  MOUNTPOINT
tank                 3.41T  5.22T   192K  /tank
tank/home             610G  5.22T   610G  /home
tank/projects         1.20T  5.22T  1.20T /srv/projects
tank/releases          42G  5.22T   42G   /srv/releases
tank/backup-recv      1.55T  5.22T  1.55T /srv/backup-recv

Interprétation : tank/releases et tank/backup-recv sont des candidats immédiats pour readonly. tank/home et tank/projects sont probablement actifs et nécessitent une stratégie différente (snapshots + quotas + permissions + peut-être séparation published/active).

Tâche 2 : vérifier l’état readonly actuel sur le pool

cr0x@server:~$ sudo zfs get -r -o name,property,value,source readonly tank
NAME             PROPERTY  VALUE  SOURCE
tank             readonly  off    default
tank/home        readonly  off    default
tank/projects    readonly  off    default
tank/releases    readonly  off    default
tank/backup-recv readonly  off    default

Interprétation : Tout est inscriptible. C’est normal au jour zéro, et exactement la raison pour laquelle les ransomwares font carnage sur les serveurs de fichiers.

Tâche 3 : mettre un dataset en lecture seule

cr0x@server:~$ sudo zfs set readonly=on tank/releases
cr0x@server:~$ sudo zfs get -o name,property,value,source readonly tank/releases
NAME          PROPERTY  VALUE  SOURCE
tank/releases readonly  on     local

Interprétation : La propriété est maintenant définie localement. Les processus existants qui supposent pouvoir écrire dans /srv/releases vont commencer à échouer, ce qui est le but — mais vous devriez coordonner le changement.

Tâche 4 : confirmer le comportement par une tentative d’écriture réelle

cr0x@server:~$ sudo touch /srv/releases/should-fail
touch: cannot touch '/srv/releases/should-fail': Read-only file system

Interprétation : C’est le mode d’échec que vous voulez lors d’une tentative de chiffrement : bruyant, immédiat, et pas « réécriture réussie de vos données ».

Tâche 5 : rendre sûr sur le plan opérationnel le fait de « permettre temporairement des écritures »

Readonly n’est pas un réglage à laisser et oublier si vous mettez parfois à jour légitimement le dataset. L’astuce est de créer une procédure de « fenêtre de maintenance » répétable qui laisse des traces.

cr0x@server:~$ sudo zfs snapshot tank/releases@before-maint-2025-12-24
cr0x@server:~$ sudo zfs set readonly=off tank/releases
cr0x@server:~$ sudo rsync -a --delete /staging/releases/ /srv/releases/
cr0x@server:~$ sudo zfs set readonly=on tank/releases
cr0x@server:~$ sudo zfs snapshot tank/releases@after-maint-2025-12-24

Interprétation : Vous avez créé deux points de restauration clairs. Si l’hôte de maintenance était compromis, vous pouvez revenir à @before-maint ou inspecter les différences entre snapshots.

Tâche 6 : renforcer le comportement des snapshots avec un hold (« pinning » de snapshot)

Un snapshot peut être détruit par un attaquant ayant des privilèges suffisants. ZFS fournit des « holds » pour empêcher la suppression tant que la retenue n’est pas levée.

cr0x@server:~$ sudo zfs snapshot tank/releases@golden
cr0x@server:~$ sudo zfs hold keep tank/releases@golden
cr0x@server:~$ sudo zfs holds tank/releases@golden
NAME                  TAG   TIMESTAMP
tank/releases@golden  keep  Wed Dec 24 10:02 2025

Interprétation : Même si quelqu’un exécute zfs destroy tank/releases@golden, cela ne fonctionnera pas tant que le hold n’est pas relâché. Ce n’est pas une protection absolue contre root sur l’hôte de stockage, mais cela augmente l’effort et évite les suppressions accidentelles.

Tâche 7 : construire une cible de réplication qui par défaut est readonly

Sur un hôte récepteur de sauvegarde, vous pouvez appliquer une politique : les données arrivent via zfs receive, mais la vue montée est en lecture seule.

cr0x@backup:~$ sudo zfs create -o mountpoint=/srv/backup-recv tank/backup-recv
cr0x@backup:~$ sudo zfs set readonly=on tank/backup-recv
cr0x@backup:~$ sudo zfs get -o name,property,value tank/backup-recv
NAME             PROPERTY  VALUE
tank/backup-recv readonly  on

Interprétation : Cela protège contre « quelqu’un qui monte les sauvegardes et écrit dedans ». Cela n’empêche pas la réception de réplication, qui écrit au niveau dataset, pas via des écritures POSIX.

Tâche 8 : répliquer des snapshots (send/receive) de façon réellement récupérable

cr0x@prod:~$ sudo zfs snapshot tank/projects@replica-001
cr0x@prod:~$ sudo zfs send -w tank/projects@replica-001 | ssh backup sudo zfs receive -u tank/backup-recv/projects

Interprétation : -u reçoit sans monter, ce qui est une hygiène de sécurité sous-estimée. Les backups non montés ne peuvent pas être consultés ou modifiés par des processus au hasard et ne font pas partie de votre namespace quotidien.

Tâche 9 : vérifier la réplication et marquer le dataset reçu readonly

cr0x@backup:~$ sudo zfs list -t snapshot tank/backup-recv/projects | tail -n 3
NAME                                     USED  AVAIL  REFER  MOUNTPOINT
tank/backup-recv/projects@replica-001        0B      -  1.20T  -
cr0x@backup:~$ sudo zfs set readonly=on tank/backup-recv/projects
cr0x@backup:~$ sudo zfs get readonly,mounted,mountpoint tank/backup-recv/projects
NAME                      PROPERTY    VALUE    SOURCE
tank/backup-recv/projects readonly    on       local
tank/backup-recv/projects mounted     no       -
tank/backup-recv/projects mountpoint  /tank/backup-recv/projects  default

Interprétation : Vous disposez maintenant d’un dataset réplique qui n’est même pas monté et qui est marqué readonly. C’est le genre de posture ennuyeuse pour les attaquants et réjouissante pour les auditeurs.

Tâche 10 : revenir rapidement après un événement de chiffrement (quand vous êtes sûr)

Le rollback est une tronçonneuse. C’est aussi le moyen le plus rapide de revenir à « opérationnel », raison pour laquelle les gens y recourent pendant les incidents. Utilisez-le avec précaution.

cr0x@server:~$ sudo zfs list -t snapshot -o name,creation tank/projects | tail -n 5
tank/projects@hourly-2025-12-24-08:00  Wed Dec 24 08:00 2025
tank/projects@hourly-2025-12-24-09:00  Wed Dec 24 09:00 2025
tank/projects@hourly-2025-12-24-10:00  Wed Dec 24 10:00 2025
tank/projects@hourly-2025-12-24-11:00  Wed Dec 24 11:00 2025
tank/projects@hourly-2025-12-24-12:00  Wed Dec 24 12:00 2025
cr0x@server:~$ sudo zfs rollback -r tank/projects@hourly-2025-12-24-10:00

Interprétation : Cela ramène le dataset à l’état du snapshot, et -r reviendra aussi en arrière sur les clones/snapshots dépendants si nécessaire. Vous ne devriez le faire que lorsque vous avez confirmé l’étendue de la compromission et que vous acceptez de perdre les changements postérieurs à ce snapshot.

Tâche 11 : si le rollback est trop destructeur, monter un snapshot en lecture seule et copier

cr0x@server:~$ sudo mkdir -p /mnt/projects-restore
cr0x@server:~$ sudo mount -t zfs tank/projects@hourly-2025-12-24-10:00 /mnt/projects-restore
cr0x@server:~$ sudo rsync -a /mnt/projects-restore/ /srv/projects/
cr0x@server:~$ sudo umount /mnt/projects-restore

Interprétation : C’est plus lent mais plus sûr pour des restaurations partielles et des enquêtes. Vous pouvez restaurer sélectivement sans rembobiner toute la timeline du dataset.

Tâche 12 : détecter une pression d’écriture suspecte avec les métriques ZFS et OS

cr0x@server:~$ sudo zpool iostat -v tank 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.41T  5.22T    220   4100   25.3M  620M
  raidz2    3.41T  5.22T    220   4100   25.3M  620M
    sda         -      -     40    690   4.3M  102M
    sdb         -      -     42    710   4.5M  104M
    sdc         -      -     46    680   4.8M  101M
    sdd         -      -     45    705   4.7M  105M

Interprétation : Un pic d’écriture soudain avec beaucoup de petites opérations est cohérent avec une réécriture de masse/chiffrement de fichiers. Ce n’est pas une preuve, mais c’est une raison d’examiner les logs SMB, la liste des processus et le churn récent des fichiers.

Tâche 13 : auditer qui peut changer les propriétés ZFS (délégation)

Si votre modèle opérationnel le permet, déléguez des droits ZFS limités plutôt que d’accorder un accès root large.

cr0x@server:~$ sudo zfs allow tank/releases
---- Permissions on tank/releases ---------------------------------------
Local+Descendent permissions:
user backupop create,mount,snapshot,send,receive

Interprétation : La délégation peut maintenir un opérateur de sauvegarde fonctionnel sans lui donner les clés pour détruire votre monde. Si tout le monde est root, readonly est une butée, pas une barrière.

Tâche 14 : rendre readonly hérité pour tout un sous-arbre

cr0x@server:~$ sudo zfs set readonly=on tank/archive
cr0x@server:~$ sudo zfs create tank/archive/2024
cr0x@server:~$ sudo zfs get readonly tank/archive/2024
NAME              PROPERTY  VALUE  SOURCE
tank/archive/2024 readonly  on     inherited from tank/archive

Interprétation : L’héritage est la manière d’éviter « on a oublié de verrouiller le nouveau dataset ». En production, l’ennemi est souvent moins la malveillance que la dérive.

Tâche 15 : confirmer le comportement visible par les clients sur NFS/SMB (sanity rapide)

Côté serveur vous pouvez valider les flags du montage. La sortie exacte varie selon la distribution et la configuration.

cr0x@server:~$ mount | grep '/srv/releases'
tank/releases on /srv/releases type zfs (ro,xattr,posixacl)

Interprétation : Vous voulez voir ro. Si cela affiche rw, vous n’avez pas obtenu readonly au niveau du montage, quelle que soit la propriété que vous avez définie.

Trois mini-récits du monde de l’entreprise

Mini-récit 1 : l’incident causé par une fausse hypothèse

L’entreprise avait une théorie propre : « Le NAS est sûr parce que seul le serveur de fichiers peut y écrire. » Et sur le tableau blanc, c’était vrai. Le serveur de fichiers exportait des partages SMB, les utilisateurs montaient des lecteurs, et le backend de stockage était « interne ». Les gens aiment le mot interne. Il sonne comme une porte verrouillée. C’est souvent un rideau.

Un lundi matin, un administrateur junior a signalé qu’un partage de projet « se comportait bizarrement ». Les fichiers ne s’ouvraient plus. Le helpdesk a remarqué une vague de tickets : les fichiers Excel ne se chargeaient pas, des PDF affichaient des erreurs, et « il y a un nouveau fichier dans chaque dossier avec des instructions ». Le rythme normal d’incident a démarré — confinement, communication, triage. Puis quelqu’un a posé la question que personne ne veut poser : « Les sauvegardes sont-elles OK ? »

Il y avait des sauvegardes. Elles étaient aussi montées en lecture-écriture sur le même serveur de fichiers parce que « c’est plus simple à restaurer ». Le malware se fiche de la simplicité de restauration. Il aime la simplicité de destruction. Le ransomware avait atterri sur un poste de travail, capturé la session de l’utilisateur, bougé latéralement avec des identifiants mis en cache, et utilisé SMB comme conçu : une API de fichiers authentifiée et rapide. Il a chiffré le partage, puis est allé joyeusement dans le chemin de sauvegarde monté et a fait de même.

La fausse hypothèse n’était pas « nous avons des sauvegardes ». C’était « les sauvegardes sont sûres parce que ce sont des sauvegardes ». Les sauvegardes ne sont sûres que lorsqu’elles sont plus difficiles à modifier que les données de production. Après le post-mortem (du genre qui se lit comme un roman d’horreur), ils ont reconstruit la cible de sauvegarde comme des réplicas ZFS reçus dans des datasets non montés et marqués readonly. La restauration est devenue un peu moins pratique. La survie est devenue beaucoup plus pratique.

La leçon opérationnelle : si votre chemin de sauvegarde est inscriptible depuis le même plan d’identités que la production, vous n’avez pas de sauvegardes — vous avez des copies supplémentaires de votre échec.

Mini-récit 2 : l’optimisation qui s’est retournée contre eux

Une équipe d’infrastructure voulait améliorer les performances pour une grosse charge média. Ils ont réorganisé les datasets pour réduire « l’overhead », en consolidant beaucoup de petits datasets en un gigantesque dataset avec des ACL larges. L’idée était simple : moins de points de montage, moins de soucis, meilleures performances. Ils ont aussi désactivé quelques plannings de snapshots « bruyants » parce qu’ils « prenaient trop de place ». Les graphiques semblaient meilleurs. L’équipe est rentrée chez elle en se sentant gagnante.

Trois mois plus tard, ils ont été frappés par un script destructeur, pas même un ransomware : un job de pipeline avec une variable de chemin buguée qui se résolvait à la racine du partage. Il a commencé à nettoyer les « anciens fichiers ». Il a tout nettoyé. L’équipe a tenté d’utiliser des snapshots et a trouvé… pas grand-chose. Le design de dataset consolidé signifiait qu’il n’y avait pas de frontières naturelles. Le compte de service du pipeline avait des droits partout parce que « il doit accéder aux médias ». Avec moins de datasets, il y avait moins d’endroits pour appliquer des politiques différentes, et avec moins de snapshots, il y avait moins de points de restauration.

Le retour de bâton n’était pas que la consolidation est toujours mauvaise. Le problème était que la consolidation a éliminé les points de contrôle. Les propriétés ZFS — readonly, plannings de snapshot, quotas, réservations — opèrent aux frontières des datasets. Si tout est un dataset, tout partage le même sort. En pratique, c’est ainsi qu’« une optimisation » devient « un point de défaillance unique ».

Ils ont fait demi-tour : l’ingest actif est resté inscriptible, les médias publiés sont devenus un dataset séparé en readonly, et les comptes de service du pipeline ont vu leurs accès limités là où ils devaient écrire. Les plannings de snapshot sont revenus avec une rétention ajustée à la réalité métier. Les performances sont restées correctes. La récupération est redevenue sensée.

La leçon opérationnelle : l’agencement des données est l’agencement de la sécurité. Si vous supprimez des frontières pour simplifier, vous supprimez aussi des endroits où appliquer des garde-fous.

Mini-récit 3 : la pratique ennuyeuse mais correcte qui a sauvé la mise

Une organisation à forte composante financière avait une habitude presque désuète : à chaque clôture mensuelle, ils « scellaient » le dataset du mois précédent. C’était un dataset ZFS séparé par période comptable, avec un nom prévisible et une checklist de runbook. Après la clôture, le dataset était mis readonly, snapshoté et répliqué vers un système secondaire. L’équipe le faisait comme une horloge, même quand personne ne regardait.

Puis est venu l’incident. Un compte de poste de travail compromis a commencé à chiffrer une large part des dossiers partagés. C’était rapide, agressif et — comme la plupart des ransomwares — indifférent aux calendriers métiers. Le serveur de fichiers s’est embrasé. La surveillance a montré une forte montée des IOPS d’écriture et de la latence. Les utilisateurs ont signalé des erreurs d’accès aux fichiers. Le chef d’incident a commencé la danse familière : isoler les endpoints, désactiver les comptes, bloquer les sessions SMB, préserver les preuves.

Quand la poussière est retombée, les mauvaises nouvelles étaient réelles : plusieurs datasets actifs étaient partiellement chiffrés. Les bonnes nouvelles étaient chirurgicales : tous les datasets scellés de fin de mois étaient intacts. Pas parce que les attaquants étaient polis, mais parce que ces datasets étaient readonly et le malware ne pouvait pas les écraser. Les données de clôture mensuelle — ce qui déclencherait un chaos réglementaire si perdu — étaient intactes et immédiatement utilisables. Ils avaient toujours un désordre à gérer, mais c’était un désordre borné.

La récupération est devenue une opération à deux vitesses : restaurer les zones de travail actives depuis des snapshots et des réplicas, tout en continuant l’activité en utilisant les datasets scellés pour le reporting et la conformité. L’organisation n’a pas « évité » l’incident. Elle a évité le mode de défaillance existentiel.

La leçon opérationnelle : les routines ennuyeuses sont celles qui vous sauvent. Pas parce qu’elles sont excitantes, mais parce qu’elles sont répétables sous stress.

Playbook de diagnostic rapide

Quand quelque chose semble aller mal — pics de latence, utilisateurs signalant des extensions de fichier étranges, erreurs d’écriture — les meilleures équipes ne débattent pas de la théorie. Elles exécutent un court playbook qui réduit rapidement les possibilités. En voici un qui fonctionne bien pour les services de fichiers soutenus par ZFS.

Première étape : confirmer si vous voyez une pression d’écriture, un churn de métadonnées, ou une application du readonly

  1. Vérifier l’I/O du pool : est-ce majoritairement des écritures ? Les opérations sont-elles petites et nombreuses ?
cr0x@server:~$ sudo zpool iostat -v tank 1 3

Interprétation : Des opérations d’écriture massives + une bande passante élevée suggèrent une réécriture/chiffrement ou une copie en masse. Des ops élevées avec faible bande passante peuvent être un churn métadonnées (tempêtes de renommage, petits fichiers).

  1. Vérifier si les datasets cibles sont readonly comme prévu (et si c’est hérité ou local) :
cr0x@server:~$ sudo zfs get -r -o name,property,value,source readonly tank/projects tank/releases

Interprétation : Si un dataset « protégé » affiche readonly=off avec local alors que vous attendiez inherited ou on, vous avez peut-être de la dérive ou un changement pendant une maintenance.

  1. Vérifier les flags de montage pour s’assurer que l’OS honore le readonly :
cr0x@server:~$ mount | egrep '/srv/releases|/srv/backup-recv'

Interprétation : Vous devriez voir ro pour les datasets en lecture seule. Si ce n’est pas le cas, considérez-le comme « non protégé ».

Deuxième étape : identifier le dataset et le client responsables (ou au moins corrélés)

  1. Trouver quel dataset est chaud :
cr0x@server:~$ sudo zfs list -o name,used,refer,quota,reservation,mountpoint -S used | head

Interprétation : Une croissance rapide peut indiquer du chiffrement produisant de nouveaux fichiers, ou un job qui déverse des données de façon inattendue.

  1. Vérifier les stats I/O par dataset (Linux) :
cr0x@server:~$ sudo zpool iostat -r -w tank 1 5

Interprétation : Recherchez une bande passante d’écriture soutenue incohérente avec les habitudes métiers normales.

  1. Corréler avec les sessions SMB/NFS (exemples ; vos commandes peuvent différer) :
cr0x@server:~$ sudo smbstatus -p | head
PID     Username     Group        Machine                                   Protocol Version  Encryption           Signing
4123    jdoe         domain users  10.10.14.27 (ipv4:10.10.14.27:51234)      SMB3_11           -                    partial

Interprétation : Un petit nombre de clients causant beaucoup de dégâts est courant. Si vous voyez un poste qui n’est pas censé toucher un partage, c’est une piste.

Troisième étape : décider si vous êtes en mode « incident de sécurité » ou « bug de performance »

Les symptômes se recoupent. Le chiffrement ressemble d’abord à un problème de performance. Les bugs de performance ressemblent parfois à du ransomware (IOPS élevés, nombreuses opérations fichier). La différence est de savoir si le contenu des données change de façon inattendue et si les tentatives d’écriture échouent à cause du readonly.

Distinguer rapidement :

  • Erreurs Readonly dans les logs applicatifs et rapports utilisateurs : suggère que les garde-fous stoppent les écritures (bien) ou que vous avez accidentellement verrouillé un dataset actif (mal).
  • Nouvelles extensions / notes de rançon : incident de sécurité.
  • Un job ou un hôte corrèle exactement : peut être de la sécurité, mais peut être un job hors de contrôle.
  • Pics de latence plus pics CPU sur les endpoints : souvent du chiffrement.

Dans tous les cas, la première action de confinement pour les partages de fichiers est la même : restreindre l’écriture, isoler les clients suspects et préserver les snapshots avant de toucher quoi que ce soit.

Erreurs courantes (symptômes + corrections)

Erreur 1 : « Readonly sur le dataset signifie que les snapshots sont sûrs »

Symptôme : Vous avez mis readonly=on, vous vous sentez confiant, puis vous découvrez que les snapshots ont disparu après un incident.

Pourquoi cela arrive : La suppression des snapshots n’est pas bloquée par le readonly du dataset. Si un attaquant a un accès administratif ZFS, il peut détruire les snapshots ou changer les propriétés.

Correction : Utilisez des holds sur les snapshots pour les points de restauration clés, restreignez les droits admin ZFS et répliquez vers une cible où les identifiants de l’attaquant n’existent pas.

Erreur 2 : activer readonly sur un dataset contenant l’état actif d’une application

Symptôme : Les applications commencent à échouer avec « Read-only file system », les bases de données refusent de démarrer, les pipelines CI cassent.

Pourquoi cela arrive : Quelqu’un a appliqué un contrôle de sécurité sans cartographier les flux de données.

Correction : Séparez les datasets : mettez l’état mutable de l’application dans un dataset écrivable ; publiez les artefacts dans un dataset readonly séparé. Si vous devez garder un seul dataset, n’utilisez pas readonly — utilisez plutôt snapshots et permissions.

Erreur 3 : supposer que readonly se propage partout sans vérifier l’héritage

Symptôme : Un nouveau dataset créé sous un arbre protégé est inscriptible.

Pourquoi cela arrive : Il a été créé ailleurs puis déplacé, ou quelqu’un a défini readonly=off localement sur un dataset enfant, outrepassant l’héritage.

Correction : Auditez avec zfs get -r readonly et prêtez attention au champ source. Pour les arbres importants, imposez des standards via des runbooks et des revues.

Erreur 4 : répliques de sauvegarde montées et consultables (et inscriptibles) depuis les identités de production

Symptôme : Les backups sont chiffrés en même temps que la production.

Pourquoi cela arrive : Pratique : les admins montent les datasets de sauvegarde pour que les restaurations soient de simples copies de fichiers. Le malware adore la commodité.

Correction : Recevez les réplicas avec zfs receive -u, gardez-les non montés par défaut et fournissez les restaurations via des workflows de mount/clone contrôlés.

Erreur 5 : « On remettra readonly off pendant les déploiements » sans processus

Symptôme : Readonly reste désactivé après un changement précipité, et personne ne s’en aperçoit avant longtemps.

Pourquoi cela arrive : Les humains oublient de refermer les portes en pleine urgence.

Correction : Utilisez une procédure de maintenance scriptée qui snapshotte avant/après et remet explicitement readonly. Auditez régulièrement la dérive des propriétés.

Erreur 6 : confondre permissions du système de fichiers et ZFS readonly

Symptôme : Un utilisateur peut encore modifier des fichiers même si « on a verrouillé », ou des écritures légitimes échouent de façon inattendue.

Pourquoi cela arrive : Les permissions POSIX/ACL et ZFS readonly sont des couches différentes. L’une contrôle qui peut écrire ; l’autre contrôle si quelqu’un peut écrire.

Correction : Utilisez les permissions pour le contrôle d’accès normal, et readonly pour l’objectif d’immuabilité et de réduction du rayon d’impact. Ne tentez pas de remplacer l’une par l’autre.

Erreur 7 : ignorer les écritures en canal secondaire (répertoires tmp, logs, métadonnées)

Symptôme : Une application « lit seulement », mais échoue sur un dataset readonly.

Pourquoi cela arrive : Beaucoup de « lecteurs » écrivent des caches, fichiers de verrouillage, fichiers temporaires ou mettent à jour des timestamps en place.

Correction : Redirigez caches et répertoires temporaires vers un emplacement écrivable. Pour les services, définissez des dossiers de cache explicites et assurez-vous que les logs vont ailleurs.

Checklists / plan étape par étape

Étape par étape : déployer readonly en production en toute sécurité (sans tout casser)

  1. Classer les datasets par comportement : active-write, published-read, archive, backup target.
  2. Séparer les datasets quand les frontières sont floues : ne luttez pas contre la réalité ; créez des points de contrôle.
  3. Choisir un dataset à faible risque (p.ex. releases, installers, archives) et piloter readonly.
  4. Snapshotter avant le changement pour que le rollback soit trivial.
  5. Activer readonly et valider à trois couches : propriété ZFS, flags de montage et comportement client.
  6. Mettre à jour les runbooks : comment effectuer des écritures planifiées (mode maintenance), qui approuve, et comment reverrouiller.
  7. Définir les attentes de monitoring : les échecs d’écriture doivent alerter, mais ne pas déclencher la panique générale.
  8. Ajouter des holds sur les snapshots pour les points de restauration critiques lorsque pertinent.
  9. Construire une cible de réplication qui reçoit les snapshots non montés ; marquez-la readonly si possible.
  10. Restreindre qui peut changer readonly et qui peut détruire des snapshots ; utilisez la délégation si elle convient à votre org.
  11. Tester la restauration trimestriellement : montez un snapshot, copiez, ou clonez et vérifiez que les applications peuvent le lire.
  12. Auditer la dérive mensuellement : readonly, statut de montage, présence des snapshots, fraîcheur de la réplication.

Checklist opérationnelle : « Sceller » un dataset après publication

  1. Créer un snapshot nommé pour l’événement/heure.
  2. Vérifier que les consommateurs lisent depuis le bon point de montage.
  3. Définir readonly=on.
  4. Mettre un hold sur le snapshot de scellage s’il s’agit d’un point de restauration clé.
  5. Réplication vers backup/DR.
  6. Enregistrer le nom du snapshot et le statut de réplication dans votre ticketing/log de changement.

Checklist opérationnelle : suspicion de ransomware sur des partages de fichiers

  1. Contenir : couper l’accès SMB/NFS pour les clients suspects ; désactiver les comptes suspects.
  2. Préserver : prendre des snapshots immédiats des datasets affectés (oui, même s’ils sont partiellement chiffrés).
  3. Évaluer : identifier le plus ancien snapshot « bon » ; vérifier l’intégrité des snapshots et l’état de la réplication.
  4. Décider : rollback vs restauration sélective. Le rollback est rapide ; la restauration sélective est plus sûre pour une récupération partielle.
  5. Récupérer : restaurer les données ; faire tourner les identifiants ; valider les endpoints ; rétablir l’accès par étapes.
  6. Durcir : déplacer les données de référence et d’archive vers des datasets readonly ; appliquer une posture d’immuabilité aux sauvegardes.

FAQ

1) ZFS readonly est-ce la même chose que du « stockage immuable » ?

Non. C’est un blocage fort au niveau système de fichiers pour un dataset, mais un acteur suffisamment privilégié peut encore changer les propriétés ou détruire des datasets/snapshots. L’immuabilité vraie requiert une séparation plus forte (domaines d’administration différents, médias hors ligne ou contrôles de gouvernance). Readonly reste très utile parce que beaucoup d’incidents ransomware opèrent avec des permissions au niveau utilisateur ou service, pas les pouvoirs d’un admin stockage.

2) Si je rends un dataset readonly, puis-je quand même y répliquer avec zfs receive ?

Généralement oui. zfs receive opère au niveau ZFS, pas via le chemin monté du système de fichiers. Readonly bloque les écritures de fichiers normales via le montage ; il ne bloque pas forcément les mises à jour administratives du dataset comme la réception d’un stream. Testez dans votre environnement et considérez les permissions de réplication comme une capacité privilégiée.

3) Readonly me protégera-t-il si le serveur de stockage est compromis ?

Pas de manière fiable. Si un attaquant a root et la capacité admin ZFS sur l’hôte de stockage, il peut souvent remettre readonly en off et détruire les snapshots. Votre protection dépend alors de contrôles extérieurs à cet hôte : cibles de backup séparées, séparation d’accès et éventuellement copies hors ligne.

4) Dois-je rendre tout mon pool readonly ?

Non. C’est un excellent moyen de découvrir quelles applications écrivent plus que vous ne le pensiez, généralement en heures de pointe. La valeur vient de rendre des datasets spécifiques readonly : archives, artefacts publiés, périodes scellées et réplicas de sauvegarde.

5) Comment gérer les mises à jour légitimes d’un dataset readonly ?

Créez une procédure de maintenance : snapshot, désactiver temporairement readonly, effectuer des écritures contrôlées, réactiver readonly, snapshotter à nouveau. L’essentiel est la répétabilité et l’auditabilité, pas les exploits héroïques.

6) Quelle est la différence entre readonly et définir des permissions/ACL pour refuser les écritures ?

Les permissions répondent à « qui peut écrire ». Readonly répond à « est-ce que quelqu’un peut écrire ». Les permissions servent pour l’opération normale. Readonly sert pour des garanties d’immuabilité et la réduction du rayon d’impact. Utilisez les deux, mais ne les confondez pas.

7) Le ransomware peut-il supprimer des snapshots depuis une machine cliente ?

Pas directement via SMB/NFS dans la plupart des configurations typiques, parce que la gestion des snapshots est une fonction d’admin stockage. Mais si votre environnement expose la suppression de snapshot via des scripts, des API ou des identifiants sur-privilégiés sur des serveurs, alors oui : les snapshots peuvent être ciblés. Considérez la capacité de supprimer des snapshots comme hautement sensible.

8) Dois-je monter les réplicas de sauvegarde ?

Seulement quand vous restaurez ou vérifiez. Garder les réplicas non montés par défaut est un moyen simple de réduire les modifications accidentelles et la probabilité qu’un processus « découvre » les backups et commence à écrire dedans.

9) Readonly a-t-il des implications de performance ?

Impact direct minimal. La plus grande histoire de performance est l’architecture que vous habilitez : moins d’écritures, moins de mises à jour de métadonnées et moins de churn sur les datasets protégés. Pendant une attaque, readonly peut améliorer les performances en empêchant les tempêtes d’écriture destructrices de réussir (même si les écritures tentées consomment toujours des ressources).

10) Quel est le contrôle compagnon le plus important à readonly ?

La séparation d’identité entre la production et les backups/réplicas. Readonly réduit les dommages, mais si la même identité compromise peut administrer le stockage et la cible de backup, vous pariez tout sur « personne n’ira si loin ». En pratique, quelqu’un y arrive éventuellement.

Conclusion

ZFS readonly n’est pas une fonctionnalité à la mode. C’est l’un de ces contrôles peu glamours qui changent l’issue des incidents. Quand vous l’appliquez aux bons datasets — données publiées, archives, périodes scellées et réplicas de sauvegarde — vous forcez le ransomware dans une voie plus étroite. Il peut toujours être bruyant. Il peut toujours faire peur. Mais il est beaucoup moins susceptible d’être fatal.

L’astuce consiste à traiter les frontières de dataset comme des frontières de sécurité, à jumeler readonly avec des snapshots en qui vous pouvez réellement avoir confiance, et à pratiquer les routines ennuyeuses : scellage, réplication, tests de restauration et audits de dérive. En stockage, les systèmes qui survivent ne sont pas les plus malins. Ce sont ceux avec des garde-fous difficiles à contourner et faciles à vérifier.

← Précédent
Docker pull terriblement lent : correctifs DNS, MTU et proxy qui fonctionnent vraiment
Suivant →
Ubuntu 24.04 : Filtrage du chemin inverse — le réglage caché qui casse le multi-homing (cas n°54)

Laisser un commentaire