Le blog des décideurs du digital sur toutes les tendances tech, architecture, organisation et produit

Une faille revient 12 ans plus tard

Cette faille a refait parler d’elle après non pas 2, mais 12 ans d’absence ! Avec un score CVSS de 9.8/10 (vulnérabilité critique), elle permet d’exécuter n’importe quel code sur le serveur des applications vulnérables.

🕵️ Explication de la faille

En 2010, une vulnérabilité a été découverte dans SpringBoot, permettant à un attaquant d’exécuter son propre code sur le serveur de l’application. Pour comprendre la faille exploitée, il faut comprendre la désérialisation.

La désérialisation, c’est l’ensemble des techniques de transformation d’une chaîne de caractères en objet compréhensible par un langage de programmation. Notamment, lorsqu’un navigateur (et derrière celui-ci, un utilisateur) envoie une requête à un serveur, celle-ci n’est constituée que de caractères : elle doit être transformée pour être compréhensible par le serveur. Au cours de ce procédé, une vulnérabilité classique (n°8 du Top 10 de l'OWASP) consiste, pour un attaquant, à manipuler une telle chaîne de caractères (et ajouter le payload, c’est-à-dire le contenu malveillant) pour forcer le serveur à effectuer certaines actions.

Newsletter sécu Désérialisation (3)Les objets Java héritent tous d’un même objet, nommé Object. Celui-ci possède un attribut spécifique, classLoader, qui représente comment/par qui la classe a été chargée en mémoire. Ce classLoader contient des attributs indiquant les chemins d’accès (URL) où trouver les classes à charger. Modifier ces attributs permet de forcer l’application à charger du code malveillant.

L’attaque de 2010 consistait donc à modifier une requête pour manipuler la propriété classLoader de l’objet une fois désérialisé. L’attaquant pouvait alors exécuter son code sur le serveur. Aucune limite à ce qu’il pouvait alors faire.

Newsletter sécurité attaque de 2010 (1)

Pour corriger la faille, les développeurs de Springboot ont ajouté la protection suivante : au cours de la désérialisation, les modifications de la propriété classLoader spécifiquement sont bloquées. On appelle cette défense une “Deny List”, parce qu’on empêche une liste d’éléments de passer. Au contraire, lorsqu’on autorise uniquement certains éléments d’une liste à passer, on parle d’“Allow List”. Les Allow Lists sont plus sécurisées que les Deny Lists, puisqu’il est facile d’oublier des éléments dangereux ; or, les attaquants ont toujours beaucoup d’imagination pour atteindre leurs objectifs. De plus, si aucun élément n’est oublié au moment où la liste est définie, il est impossible de prévoir comment le reste du code va évoluer dans le futur.

C’est précisément ce qui s’est passé ici : en avril 2022, soit près de 12 ans plus tard, des chercheurs ont découvert une façon de contourner la Deny List, en utilisant une fonctionnalité introduite en 2017 dans Java 9 : les modules. Au lieu d’avoir comme payload : class.classLoader, il est possible d’utiliser class.module.classLoader. La Deny List initiale ne vérifie pas ça, et une attaque est à nouveau possible.

2 jours après la divulgation aux contributeurs de Springboot, une nouvelle version a été publiée. Cette fois, la stratégie a changé, et c’est une Allow List qui est utilisée : lorsque les propriétés de la classe Object sont parcourues, la désérialisation n’est effectuée que si l’attribut se finit par “name”. De quoi se protéger contre l’attaque nouvellement découverte, et se prémunir d’une nouvelle découverte dans les dizaines d’années à venir.

🛡 Comment se protéger ?

  • Mettre à jour Springboot pour ne plus être vulnérable : l’attaque qui a été conçue nécessite des configurations spécifiques que nous n’avons pas détaillées ici, mais nous ne sommes pas à l’abri que de nouvelles techniques d’exploitation soient découvertes.
    Les versions impactées : 5.3.0 à 5.3.17, 5.2.0 à 5.2.19, et toutes les versions plus anciennes
  • Utiliser des Allow Lists plutôt que des Deny Lists pour des stratégies de défense : les attaquants auront plus de mal à les contourner.
  • Ne pas tenter de coder sa propre fonction de désérialisation, mais utiliser des librairies open source. Il y a beaucoup de cas limites sur lesquels des dizaines de développeurs ont appris et amélioré leur code. Il est impossible de penser à tous ces cas limites en repartant de zéro (ou même de les connaître).

🏹 Pour aller plus loin

Nous avons pour ambition de sécuriser le web, et pour atteindre cet objectif, nous avons besoin de vous ! Si vous avez des questions, des suggestions ou le moindre doute, n'hésitez pas à contacter notre équipe sécurité : security@theodo.fr.

 

Topics: Sécurité