
Par Eliot Rabaud
Failles critiques en octobre, Halloween avant l’heure : comment ne pas paniquer ?
Fin octobre, mon téléphone n’arrêtait pas de sonner. Clients, confrères, équipes d’exploitation : tout le monde voulait savoir ce qu’il fallait corriger, et dans quel ordre. Il faut dire que le mois a été chargé.
Le 12 octobre, GitLab corrigeait une faille notée 10 sur 10 (CVE-2026-97229). Le 21, PHP publiait en urgence le correctif de PHP2Shell, deux failles notées 9,2 qui concernent toute installation PHP servant des pages web. Le même jour, GitLab corrigeait une seconde faille notée 10 (CVE-2026-110264). Et le 27, Anthropic publiait le détail d’un exploit visant une faille du noyau Linux notée 9,8 (CVE-2026-98432) : prendre le contrôle d’un serveur en root, à distance, sans aucun identifiant.
Face à une telle série, la tentation est de tout traiter dans l’urgence, ou de commencer par la faille qui fait le plus de bruit. Le score CVSS n’aide pas beaucoup à trier : les quatre sont entre 9,2 et 10, donc toutes critiques.
Apprendre à trier compte d’autant plus pour la suite. L’exploit du noyau a été écrit par un modèle d’IA d’Anthropic, à partir d’un bug que ce même travail de recherche avait fait remonter. Avec l’IA au service de la recherche offensive, chez les défenseurs comme chez les attaquants, des mois comme celui d’octobre vont très probablement se reproduire, et plus souvent. Patcher tout en urgence à chaque fois ne tiendra pas longtemps.
Nous allons analyser trois de ces failles critiques d’octobre, le noyau Linux, PHP2Shell et la première faille GitLab, pour comprendre comment réagir de manière constructive à l’aide d’autres indicateurs, à commencer par l’EPSS. Vous verrez que pour une gravité comparable, leurs probabilités d’exploitation vont de moins de 1 % à presque 100 %.
Sommaire
- Les trois failles en détail
- Ce que dit CVSS, et ce qu’il ne dit pas
- L’EPSS, ou la question de la probabilité
- Les trois failles côte à côte
- Ce que l’EPSS ne fait pas
- Concrètement, que faire
- Pour finir
Les trois failles en détail
Le noyau Linux (CVE-2026-98432)
Le bug est corrigé par ce commit d’Eric Dumazet, signalé par Xinyang Ge, chercheur chez Anthropic. Le correctif tient en deux lignes : deux kfree() remplacés par des kfree_rcu(). Autrement dit, une zone mémoire n’est plus libérée immédiatement, mais seulement quand plus aucun processeur n’est en train de la lire. Ce qui se cache derrière, c’est une race condition entre deux processeurs.
Le scénario, étape par étape :
- Un client ouvre une connexion TCP en IPv4 avec des options IP dans son paquet SYN (Record Route ou Timestamp, des options rarement utilisées). Le noyau range ces options en mémoire. Leur contenu est choisi par le client, donc par l’attaquant.
- Quand la connexion s’établit, le noyau confie ces options au nouveau socket sans les copier. Deux structures pointent alors vers la même zone mémoire : si l’une la libère, l’autre continue de s’en servir sans le savoir.
- Si le client renvoie au même moment le même SYN, un autre processeur peut encore être en train de lire ces options pour répondre, alors que le premier vient de les libérer.
C’est un use-after-free : le noyau lit, et parfois écrit, dans une zone mémoire qui ne lui appartient plus. Si l’attaquant parvient à y placer ses propres données entre-temps, le noyau les traite comme légitimes. Selon le moment, il peut alors lire de la mémoire du noyau, ou en modifier. Le bug existe depuis Linux 4.4, soit une dizaine d’années.
Comme il s’agit d’une race condition, l’attaquant ne maîtrise pas le moment exact et doit tenter sa chance un grand nombre de fois. En général, une tentative ratée fait juste échouer la connexion, sans planter la machine : il peut donc réessayer autant qu’il veut. C’est ce qui explique les durées ci-dessous.
Anthropic a publié le 27 octobre le détail de son exploit, sans le code. Il se déroule en deux temps :
- Contourner le KASLR. Le KASLR place le noyau à une adresse aléatoire au démarrage, pour qu’un attaquant ne sache pas où viser. L’exploit gagne la race condition de façon à ce que le noyau renvoie dans sa réponse SYN-ACK quelques octets de trop, lus dans sa propre mémoire. Dès qu’un de ces octets contient un pointeur du noyau, l’attaquant connaît la disposition de la mémoire. Dans la démonstration d’Anthropic, cette première étape prend 48 minutes, le temps de gagner assez de fois la race condition pour récupérer un pointeur utile. Sans cette étape, il viserait à l’aveugle et ferait planter le serveur bien plus souvent qu’il n’en prendrait le contrôle.
- Prendre la main. Le même bug sert ensuite à écraser un pointeur de fonction, c’est-à-dire une adresse que le noyau appellera plus tard. Le noyau exécute alors du code choisi par l’attaquant, qui lance une commande en root. Cinq minutes de plus. En root, l’attaquant a tous les droits sur la machine : lire les données, installer une porte dérobée, rebondir vers le reste du réseau.
Il y a une condition que les titres ont souvent oubliée. L’exploit d’Anthropic vise des serveurs avec un listener MPTCP (Multipath TCP, une extension qui permet d’utiliser plusieurs chemins réseau pour une même connexion). Anthropic n’explique pas pourquoi MPTCP est nécessaire. Le bug lui-même est dans le TCP IPv4 ordinaire, et personne n’a encore montré publiquement d’exécution de code sans MPTCP. En pratique, un serveur sans listener MPTCP n’est pas concerné par cet exploit précis. Il reste vulnérable au bug, et rien ne garantit qu’un autre chemin d’exploitation ne sera pas trouvé.
Et c’est là qu’entre le langage Go. Depuis Go 1.24, un programme Go qui écoute sur un port active MPTCP par défaut sous Linux. L’équipe sécurité de Go l’a rappelé le 29 octobre. Caddy, Traefik, beaucoup d’outils d’infra récents sont écrits en Go. Vous pouvez donc avoir un listener MPTCP sur un serveur sans l’avoir jamais configuré, simplement parce qu’un de ces outils y écoute. Ce n’est pas le seul cas possible : n’importe quel programme peut en ouvrir un, et l’équipe Go prévient elle-même que tous les exploits futurs ne dépendront peut-être pas de MPTCP.
Pour être précis sur le score : la faille est notée 9,8 par l’équipe CVE du noyau, et Red Hat s’est aligné sur 9,8 début novembre après un score provisoire plus bas.
Au 3 novembre : aucun exploit public, aucune exploitation constatée. Marcus Hutchins a signalé des scans qui cherchent des serveurs MPTCP sur le port 443, et il a compté environ 760 000 machines qui acceptent une connexion TLS en MPTCP (The Stack). Ça ne dit pas combien sont vulnérables.
PHP2Shell (CVE-2026-109618 et CVE-2026-109619)
Deux failles dans PHP lui-même, corrigées le 21 octobre dans les versions 8.5.12, 8.4.27, 8.3.36 et 8.2.35. Toutes deux touchent la façon dont PHP gère sa mémoire d’une requête à l’autre.
La première, CVE-2026-109618 (RCE via OOM corruption), exploite la gestion des out-of-memory. Quand une requête dépasse la mémoire autorisée, PHP l’abandonne brutalement (avec un longjmp()) et laisse derrière lui de la mémoire à moitié initialisée. Le nettoyage de fin de requête relit ensuite cette mémoire comme si elle était valide. Concrètement, un attaquant capable de provoquer un out-of-memory, par exemple avec une requête multipart construite pour ça, amène PHP à manipuler des données qu’il contrôle en partie, jusqu’à exécuter du code.
La seconde, CVE-2026-109619 (RCE via stale global state), laisse des variables globales pointer vers la mémoire d’une requête terminée. La requête suivante, traitée par le même processus PHP, les réutilise. Résultat : une requête de l’attaquant peut piéger celle d’après : c’est encore un use-after-free, mais d’une requête HTTP à l’autre.
Le point qui fait mal : d’après l’avis officiel de PHP, sur Apache avec mod_php, l’attaque passe par l’analyse automatique du corps de la requête, avant qu’une seule ligne de code de l’application ne s’exécute. Ni l’authentification, ni les contrôles du framework, ni la qualité du code n’entrent en jeu. Si PHP sert des pages, il est exposé. Seule la mise à jour corrige vraiment ; en attendant, PHP suggère par exemple de bloquer en amont les requêtes multipart si le site n’en a pas besoin.
Côté exploitation, tout est allé très vite. Du code d’exploitation circulait dès le 21 octobre. Les honeypots de watchTowr ont vu des attaques le jour même. Le CERT japonais a signalé le 26 octobre « de nombreux PoC » publiés et un trafic d’attaque continu. La CISA a ajouté les deux failles à son catalogue des vulnérabilités exploitées (KEV) le 26 octobre, en laissant trois jours aux administrations fédérales américaines pour corriger (alerte CISA). Une entrée au KEV signifie que l’exploitation n’est plus une hypothèse : elle a été constatée.
Une nuance tout de même : tous ces PoC ne marchent pas partout. La réussite dépend de la version, de l’environnement et de la disposition mémoire. Mais il suffit qu’un seul fonctionne sur votre serveur.
GitLab (CVE-2026-97229)
Notée 10 sur 10, et c’est la plus intéressante à décortiquer. Rien n’est vulnérable « par défaut » : c’est l’attaquant qui apporte la regex piégée. Il doit pouvoir déposer dans un projet un fichier .gitlab-ci.yml (celui qui décrit les pipelines CI/CD) contenant une expression régulière de son choix, par exemple sous une règle rules:exists:regexp. Tout le détail qui suit vient de l’analyse technique de Rapid7.
La chaîne tient en cinq temps :
- GitLab valide la regex. Avant de s’en servir, il la passe au crible : longueur de la source, bornes des répétitions, taille du programme compilé plafonnée à 1 Mo. Pour ces contrôles, il compile la regex dans un encodage donné. La regex piégée passe tous les tests.
- Puis il la recompile en UTF-8. Plus tard, GitLab évalue la regex contre les chemins de fichiers du dépôt. Si un chemin contient des caractères codés sur quatre octets en UTF-8, le moteur de regex de Ruby (Onigmo) recompile la regex pour cet encodage. C’est le cœur du problème : ce qui a été vérifié n’est pas ce qui est exécuté. Cette seconde compilation échappe aux contrôles de la première.
- Un entier déborde. Pour décider s’il « déroule » une répétition (recopier le motif à l’avance autant de fois qu’il se répète), Onigmo calcule la place que ça prendrait : en gros,
taille du motif × nombre de répétitions. Ce calcul se fait dans un entier signé de 32 bits, qui ne peut pas monter au-delà de 2 147 483 647 (INT_MAX). L’attaquant choisit ses valeurs pour que le produit dépasse ce plafond. L’entier n’a pas la place de stocker un nombre aussi grand en mémoire : il « déborde » et repart en négatif. Dans l’exemple de Rapid7, le calcul donne 2 147 513 555, soit à peine 29 908 de trop, et c’est suffisant. - La vérification saute. Comme le résultat est devenu négatif, le test « est-ce assez petit pour dérouler ? » répond oui à tort. Onigmo déroule alors un programme énorme. Dans ce programme trop gros, les adresses de saut internes sont elles aussi stockées sur des entiers trop petits, qui débordent à leur tour. Certains sauts du moteur ne pointent donc plus vers du code légitime, mais vers des données que l’attaquant contrôle.
- La regex devient une commande. À partir de là, Rapid7 a montré qu’on pouvait détourner le fil d’exécution du moteur jusqu’à un appel système, et faire lancer une commande du système d’exploitation. Je ne reproduis pas la construction de la charge, elle est dans leur analyse. Le point à retenir : la commande s’exécute avec l’utilisateur
gitdu serveur, celui qui possède les dépôts. L’attaquant accède donc au code source hébergé, et potentiellement aux secrets des pipelines.
Un détail que souligne Rapid7 : l’évaluation ne passe même pas par la création d’un pipeline. Elle est déclenchée par l’API de vérification (« lint ») de la configuration CI, accessible sans authentification sur un projet public. Correctifs le 12 octobre (19.2.8, 19.3.5, 19.4.2).
Reste donc à pouvoir pousser ce fichier et ce chemin piégé dans un projet accessible. Sur une instance où n’importe qui peut créer un compte et un projet, cette barrière n’existe plus. Elle tombe aussi dès qu’un compte légitime est compromis : un prestataire, un stagiaire, un ancien salarié dont le compte n’a jamais été désactivé. La CISA a classé la faille « automatisable », exploitable en masse par un script, et l’a ajoutée au KEV le 29 octobre.
Ce que dit CVSS, et ce qu’il ne dit pas
Le CVSS mesure la gravité d’une faille dans l’absolu : accessible par le réseau ou pas, besoin d’un compte ou pas, impact sur la confidentialité, l’intégrité, la disponibilité. C’est une description de la faille. Il ne dit rien de ce que font les attaquants.
Les trois failles cochent les mêmes cases : réseau, pas de compte, pas d’action de la victime, impact total. Elles finissent donc toutes entre 9,2 et 10.
Le cas de PHP2Shell est presque ironique. Son vecteur CVSS 4.0 indique une complexité d’attaque élevée (AC:H) avec des conditions préalables (AT:P). Sur le papier, c’est la plus difficile des trois. C’est pourtant celle qui a été exploitée le jour même du correctif. À l’inverse, le noyau est noté complexité faible (AC:L), alors qu’il faut gagner une race condition, découvrir la disposition de la mémoire et attendre 48 minutes. Red Hat avait d’ailleurs d’abord retenu AC:H, d’où son score provisoire plus bas. La différence entre « faible » et « élevée » se joue sur une interprétation.
Le CVSS reste utile : il dit ce qui se passe si la faille est exploitée. Il ne dit pas si elle va l’être.
L’EPSS, ou la question de la probabilité
L’EPSS (Exploit Prediction Scoring System) répond à une question différente : quelle est la probabilité que cette faille soit exploitée quelque part dans le monde dans les 30 prochains jours ? Il est publié chaque jour, gratuitement, par le FIRST, l’organisme qui gère aussi le CVSS.
Sous le capot, c’est un modèle d’apprentissage automatique (des arbres de décision boostés, XGBoost) qui mange environ 2 850 variables par faille. On y trouve l’existence de code d’exploitation public, des modules Metasploit ou de scanners, les mentions sur les réseaux sociaux et les forums, l’éditeur, le type de faille, l’âge de la CVE, le nombre de références. Il est entraîné sur ce qui s’est réellement passé : détections d’attaques remontées par les pots de miel, les sondes de détection d’intrusion et les antivirus d’une douzaine de partenaires (fonctionnement détaillé).
Il donne deux chiffres :
- la probabilité, entre 0 et 1 : 0,05 veut dire 5 % de chances d’exploitation dans les 30 jours ;
- le centile : la place de la faille parmi toutes les CVE. 98 % veut dire que la faille est plus menaçante que 98 % des autres.
Pour avoir une idée des ordres de grandeur, seules 1,5 à 3 % des failles publiées sont exploitées sur une période de 30 jours, et le score médian tourne autour de 0,7 % (guide d’utilisation). Un score de 25 %, c’est donc énorme.
Les trois failles côte à côte
Scores relevés via l’API du FIRST le 3 novembre 2026 :
| Noyau Linux | PHP2Shell | GitLab | |
|---|---|---|---|
| CVE | 2026-98432 | 2026-109618 | 2026-97229 |
| CVSS | 9,8 | 9,2 (v4) | 10 |
| EPSS | 0,76 % | 99,999 % | 27,7 % |
| Centile EPSS | 55 % | 99,998 % | 98 % |
| Exploit public | Non | Oui, plusieurs | Oui (Rapid7) |
| Catalogue KEV | Non | Oui, 26 oct. | Oui, 29 oct. |
Pour la même note de gravité, la probabilité d’exploitation varie d’un facteur 130. La faille du noyau qui a fait paniquer tout le monde se situe à peine au-dessus de la médiane des CVE. PHP2Shell, elle, est au sommet absolu de l’échelle.
L’historique est encore plus parlant :
| Date | Noyau | PHP2Shell | GitLab |
|---|---|---|---|
| 22 oct. | 0,17 % | 5,3 % | 0,55 % |
| 24 oct. | 0,17 % | 11,8 % | 0,55 % |
| 25 oct. | 0,39 % | 99,98 % | 18,4 % |
| 3 nov. | 0,76 % | 99,999 % | 27,7 % |
Le score du noyau a quand même été multiplié par plus de quatre depuis le 24 octobre. Il faut le surveiller. Mais on reste loin des deux autres.
Ce que l’EPSS ne fait pas
Je ne vais pas vous vendre l’EPSS comme une boule de cristal. Il a des limites, et le tableau ci-dessus en montre une très bien.
Il a du retard. PHP2Shell était exploitée dès le 21 octobre. Le 22, son EPSS était à 5 %, et il n’a basculé qu’au 25. Le modèle a besoin que les signaux s’accumulent. Pendant les premiers jours d’une faille, un EPSS bas ne veut pas dire grand-chose.
Il ne connaît pas votre parc. L’EPSS est un chiffre mondial. Il ne sait pas si votre GitLab est ouvert sur Internet ou caché derrière un VPN, ni si vos serveurs tournent un service Go. Une faille à 0,76 % sur un serveur exposé qui fait tourner tout votre business mérite plus d’attention que la même faille sur un poste de test isolé.
Un score bas n’est pas un feu vert. 0,76 %, c’est faible pour une faille. Sur cent serveurs exposés, ce n’est plus négligeable.
Le KEV passe avant. GitLab est à 27,7 % alors que la CISA a constaté son exploitation. Ce n’est pas une contradiction, explique le FIRST : le KEV regarde le passé (elle a été exploitée), l’EPSS regarde les 30 prochains jours. Une faille dans le KEV se traite en priorité, quel que soit son EPSS.
Dernier piège : ne multipliez pas l’EPSS par le CVSS pour obtenir un « score de risque ». Le FIRST le déconseille noir sur blanc, le résultat ne veut rien dire.
Concrètement, que faire
Pas besoin d’outil payant pour commencer. Voilà l’ordre que je recommande, inspiré de ce que fait désormais la CISA avec sa directive BOD 26-04, qui ne trie plus par CVSS mais selon l’exposition, de l’exploitation constatée et de l’automatisation.
- Dans le KEV et exposé sur Internet : maintenant. En heures, pas en jours. C’était PHP2Shell et GitLab le 26 octobre. Et si un PHP 8.1 ou plus ancien ne peut pas être mis à jour, la CISA conseille carrément de le débrancher.
- EPSS élevé et exposé : cette semaine. Le FIRST indique qu’un seuil autour de 0,04 (4 %) sélectionne à peu près autant de failles que la catégorie « critique » du CVSS, mais des failles qui ont de vraies chances d’être exploitées. Adaptez le seuil à votre capacité à patcher.
- Le reste : dans votre cycle normal, en commençant par ce qui est exposé et ce qui est critique pour votre activité. Surveillez l’EPSS chaque semaine, il bouge.
Le noyau Linux tombait dans la troisième catégorie, avec des mesures temporaires faciles à appliquer en attendant le reboot. Pour vérifier si vous avez des listeners MPTCP :
ss -M -l -n -p -ePour couper MPTCP en attendant le nouveau noyau, ce que propose Akamai :
sysctl -w net.mptcp.enabled=0
sysctl -w net.ipv4.tcp_migrate_req=0Ce réglage ne touche pas les sockets déjà ouverts : redémarrez les services concernés. Côté Go, la variable d’environnement GODEBUG=multipathtcp=0 fait la même chose programme par programme. Ça réduit le risque sans le supprimer, le seul vrai correctif reste le noyau à jour.
Et pour interroger l’EPSS de vos CVE, une ligne suffit :
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2026-98432,CVE-2026-109618,CVE-2026-97229"Le catalogue KEV est téléchargeable en JSON sur le site de la CISA, et l’EPSS a une API gratuite. Croiser les deux tient en une trentaine de lignes de Python :
import json, urllib.request
# Vos CVE du moment (celles qui touchent des versions que vous faites tourner).
cves = ["CVE-2026-98432", "CVE-2026-109618", "CVE-2026-97229", "CVE-2026-110264"]
# EPSS : toutes les CVE en un seul appel.
u = "https://api.first.org/data/v1/epss?cve=" + ",".join(cves)
epss = {d["cve"]: float(d["epss"]) for d in json.load(urllib.request.urlopen(u))["data"]}
# Catalogue des vulnérabilités déjà exploitées (KEV) de la CISA.
k = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
kev = {v["cveID"] for v in json.load(urllib.request.urlopen(k))["vulnerabilities"]}
# Tri : d'abord ce qui est dans le KEV, puis par EPSS décroissant.
for cve in sorted(cves, key=lambda c: (c not in kev, -epss.get(c, 0))):
marque = "KEV" if cve in kev else " "
print(f"{marque} EPSS {epss.get(cve, 0):6.1%} {cve}")Donnez-lui la liste des CVE qui vous concernent, il les classe : d’abord celles que la CISA a vues exploitées, puis par probabilité décroissante. Sur nos quatre exemples, il place PHP2Shell puis la première faille GitLab en tête (toutes deux dans le KEV), ensuite la seconde faille GitLab, et le noyau Linux en dernier. C’est le squelette de ce que vendent les outils de gestion des vulnérabilités, et ça change déjà la façon de trier.
Pour finir
Je ne dis pas qu’il ne fallait pas patcher le noyau. Il fallait le faire, dans les jours qui suivaient. Mais un admin qui a passé son vendredi soir sur ses noyaux pendant que son GitLab ouvert aux inscriptions restait en 19.4.1 s’est trompé d’ordre. Le CVSS lui disait que tout brûlait au même niveau. L’EPSS et le KEV lui auraient dit où était vraiment le feu.
Il reste une condition pour que tout ça marche : savoir ce que vous avez. Quelle version de PHP tourne derrière ce vieux site vitrine ? Ce GitLab est-il ouvert sur Internet ? Ce reverse proxy est-il écrit en Go ? Sans inventaire, l’EPSS ne sert à rien, parce que vous ne savez pas à quoi l’appliquer. C’est précisément ce que fait l’audit externe Découverte : le tour de ce que votre entreprise expose sur Internet, avec les versions. Et si vous voulez mettre en place une routine de correctifs qui tient la route, on peut en parler pendant une consultation.
Articles sur le même thème
- Pentest

Audit d'intrusion
Audit d’intrusion, ou pentest : simuler des attaques sur un système interne, externe, cloud ou web pour corriger les failles avant les attaquants.
- Cybersécurité

Inventaire de hacks réussis : et si ce n’était pas si compliqué ?
Cinq hacks célèbres (Colonial Pipeline, Equifax, Change Healthcare, France Travail, frigos de supermarché) : des entrées banales, et ce qu’elles ont coûté.
- Pentest

RGPD et Pentest
Comment le pentest aide à tenir les obligations de sécurité du RGPD : articles clés (25, 32, 33, 35), sanctions, et pourquoi un audit prouve votre diligence.
