Skip to main content

Gérer les vulnérabilités de sécurité dans Spring Boot

Écrit par
feature open source

29 novembre 2023

0 minutes de lecture

Dans le développement logiciel, la gestion des dépendances est essentielle pour créer des applications robustes et sécurisées. Spring Boot, très apprécié des développeurs Java, facilite la création d’applications, mais il ne faut pas s’arrêter aux apparences. Il est crucial de garder vos dépendances à jour pour garantir le bon fonctionnement de vos projets Spring Boot et leur permettre de résister à des menaces en constante évolution.

La sécurité est un aspect essentiel de la gestion des dépendances Spring Boot. De nouvelles vulnérabilités logicielles sont régulièrement découvertes. En gardant les dépendances de votre projet à jour, vous renforcez sa protection numérique. Les dépendances obsolètes peuvent être comme des portes déverrouillées, qui invitent les menaces potentielles à s’introduire : mieux vaut éviter cela.

Détecter les vulnérabilités dans Spring Boot

Les outils d’analyse de la composition logicielle (SCA) sont très utiles aux développeurs. Ils facilitent la gestion des dépendances, le traitement des vulnérabilités de sécurité, la gestion des licences et la conformité de vos projets logiciels. En utilisant Snyk Open Source comme solution SCA, vous pouvez facilement vérifier si vos packages Spring Boot contiennent des vulnérabilités.

Dans mon projet d’exemple, j’ai détecté plusieurs vulnérabilités. La première est une vulnérabilité de sécurité de gravité élevée dans `netty-codec-http2`. Il s’agit d’une dépendance transitive apportée par `spring-boot-start-webflux`, comme vous pouvez le voir ci-dessous.

Détails de la vulnérabilité de io.netty:netty-codec-http2, identifiée comme un déni de service avec un score de 725 et une mise à niveau recommandée pour la corriger.

La deuxième vulnérabilité que je souhaite aborder est un problème d’exécution de code arbitraire de gravité moyenne, introduit par le package `snakeyaml`. Il s’agit également d’une dépendance transitive, cette fois apportée par `spring-boot-starter-security`.

Rapport de vulnérabilité pour org.yaml:snakeyaml indiquant une exécution de code arbitraire, avec un score de 405, introduite par Spring Boot Security 2.7.16.

Je ne vais pas détailler aujourd’hui les problèmes liés à chacune de ces vulnérabilités, mais vous trouverez plus d’informations sur le problème `snakeyaml` dans cet article de blog. Concentrons-nous sur la résolution du problème et la mise en œuvre de la meilleure solution.

Corriger les packages vulnérables dans votre application Spring Boot

Pour la première vulnérabilité, la solution est clairement indiquée. Mon application repose sur Spring Boot 2.7.16 ; `spring-boot-starter-webflux` est donc également en version 2.7.16.

La mise à jour du starter Webflux vers la version 2.7.17 devrait résoudre le problème. Il existe plusieurs façons

de procéder, mais elles ne sont pas toutes recommandées.

En général, votre manifeste Spring Boot ressemble au code suivant :

Maven :

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.7.16</version>
   <relativePath/>
</parent>
…
<dependencies>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-webflux</artifactId>
   </dependency>
  …
</dependencies>

Gradle :

plugins {
 …
 id 'org.springframework.boot' version '2.7.16'
 id 'io.spring.dependency-management' version '1.1.3'
}
…
dependencies {
 implementation 'org.springframework.boot:spring-boot-starter-security'
 implementation 'org.springframework.boot:spring-boot-starter-webflux'
 …
}

Mettre à jour le starter Spring Boot

Le numéro de version des différents `spring-boot-starters` est défini par `spring-boot-starter-parent` (Maven) ou par le plugin `org.springframework.boot` dans Gradle. 

La principale raison est que tous ces packages starter font partie de la même version de Spring et sont testés ensemble.

Pour la première vulnérabilité détectée dans mon projet, la correction suggérée consiste à mettre à jour `spring-boot-starter-webflux` vers la version 2.7.17 afin de résoudre la vulnérabilité de sécurité de gravité élevée. Cela laisse penser qu’il suffit de corriger le package Webflux, ce que je pourrais faire en spécifiant une version précise, comme ci-dessous.

Maven :

   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-webflux</artifactId>
       <version>2.7.17</version>
   </dependency>

Gradle :

implementation 'org.springframework.boot:spring-boot-starter-webflux:2.7.17'

Mais arrêtez-vous là ! Ce n’est pas la méthode recommandée pour résoudre le problème. La version précise 2.7.17 est utilisée à la place de la version parent. Même si cela peut fonctionner puisqu’il s’agit d’une version corrective, ce n’est ni la meilleure solution ni la plus sécurisée. Le versionnage sémantique ne garantissant pas la stabilité des API, nous ne pouvons pas être sûrs que cela fonctionnera. Mais l’argument le plus important, c’est qu’une nouvelle version complète de Spring Boot est probablement disponible.

Vous vous souvenez que ces starters vont ensemble ? La meilleure solution consiste donc à mettre à jour toute votre distribution Spring Boot vers la version 2.7.17. C’est encore plus important pour les versions mineures ou majeures d’un package, qui peuvent entraîner des ruptures d’API et des problèmes de compatibilité. Dans cet exemple, mettez à jour le parent (Maven) ou le plugin (Gradle), plutôt que les starters individuellement.

Maven :

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.7.17</version>
   <relativePath/>
</parent>

Gradle :

plugins {
 …
 id 'org.springframework.boot' version '2.7.17'
}

Je recommande à tout le monde de faire un effort supplémentaire et de mettre à jour toute la version de Spring Boot vers la dernière version adaptée. Pour savoir laquelle choisir, rendez-vous simplement sur https://start.spring.io.

Interface de Spring Initializr présentant les sélections du projet, du langage et de la version de Spring Boot, avec Gradle-Groovy, Java et Spring Boot 2.7.17 sélectionnés.

Mettre à jour les dépendances transitives

Pour le deuxième problème, Snyk a constaté qu’aucune recommandation de correction claire n’était disponible dans mon application. Pour l’instant, aucune version de `spring-boot-starter` dépourvue de cette dépendance transitive non sécurisée n’est disponible. En revanche, une version mise à jour de la dépendance transitive existe. La mise à jour de `snakeyaml` vers la version 2.0 résoudra le problème.

Encore une fois, il ne s’agit que d’un exemple. Une version mise à jour de `spring-boot-starter` pourrait déjà être disponible lorsque vous lirez ces lignes : pensez donc à vérifier. Pour en savoir plus sur la vulnérabilité SnakeYaml, consultez notre article de blog dédié.

Mettre à jour le paramètre de version

Commencez par vérifier si la version du package à mettre à jour est définie par une propriété Spring Boot. La documentation Spring Boot contient une annexe répertoriant les versions des dépendances pour chaque version. Vous y trouverez également les propriétés de version. Ces propriétés peuvent être remplacées dans Maven et Gradle afin d’utiliser une version plus récente de la dépendance transitive. 

Avec Maven, vous pouvez ajouter une propriété dans la section des propriétés.

<properties>
   <snakeyaml.version>3.0</snakeyaml.version>
</properties>

Avec Gradle, vous pouvez modifier cette propriété dans un fichier `gradle.properties` :

snakeyaml.version=3.0

Cette méthode est préférable à la gestion des dépendances, car `snakeyaml` est une bibliothèque unique. Cependant, dans de nombreux cas, il y a plusieurs bibliothèques. La version peut faire référence à une BOM (nomenclature logicielle), à ne pas confondre avec une SBOM : elle représente un ensemble de groupes de packages qui doivent être utilisés ensemble et qui ont essentiellement la même version, par exemple un package d’API et un package d’implémentation. Les deux doivent être dans la même version pour fonctionner comme prévu.

Déclaration de gestion des dépendances

Une autre option consiste à utiliser les mécanismes de votre outil de build pour mettre à jour les dépendances transitives. Cette méthode ne doit être utilisée que si vous ne pouvez pas mettre à jour la propriété de version comme indiqué dans la section précédente.

Avec Maven, on l’ajoute généralement au bloc `dependencyManagement`. Ce bloc garantit que la version mise à jour qui y est indiquée est utilisée chaque fois que la bibliothèque est appelée comme dépendance transitive.

Maven :

<dependencyManagement>
   <dependencies>
       <dependency>
           <groupId>org.yaml</groupId>
           <artifactId>snakeyaml</artifactId>
           <version>2.2</version>
       </dependency>
   </dependencies>
</dependencyManagement>

Comme nous utilisons le plugin dependency-management pour Spring dans notre fichier Gradle, nous disposons de fonctionnalités très similaires dans Gradle. Notez que ce plugin a été ajouté par l’initialiseur Spring Boot lors de la création de la structure de mon projet.

Gradle :

dependencyManagement {
   dependencies {
       dependency 'org.yaml:snakeyaml:2.2'
   }
}

Si vous n’utilisez pas le plugin `io.spring.dependency-management`, vous pouvez également ajouter des contraintes aux dépendances transitives dans Gradle afin de mettre à jour une dépendance transitive, comme ci-dessous. Gardez à l’esprit que ces contraintes ne fonctionnent pas bien avec le plugin Spring `dependency-management`. Il faut donc choisir l’un ou l’autre.

dependencies {
    …
    constraints {
        implementation('org.yaml:snakeyaml:2.2') {
            because 'previous versions have a security issue'
        }
    …
}

Analyser vos applications Spring Boot avec Snyk

Analyser votre application Spring Boot avec Snyk est essentiel pour garantir la sécurité et la stabilité de vos logiciels. Snyk vous aide à détecter les vulnérabilités dans les dépendances de votre application, que des acteurs malveillants pourraient exploiter si elles ne sont pas corrigées. Après avoir lu cet article, vous savez également comment appliquer au mieux les recommandations de correction de Snyk.

L’analyse régulière de votre base de code permet de traiter les problèmes de sécurité de manière proactive et de réduire les risques de fuite de données et d’autres incidents de sécurité. Intégrez donc l’analyse à votre processus habituel et assurez-vous de savoir comment réagir lorsqu’une vulnérabilité est détectée.

Ci-dessous, j’ai analysé mon application avec Snyk CLI avant et après les corrections. J’ai choisi de mettre à jour la version générale de Spring Boot et la propriété de version spécifique de `snakeyaml`.

Avant :

Sortie du terminal affichant les résultats de l’analyse Snyk des dépendances Spring Boot, avec 14 problèmes et 21 chemins vulnérables.

Après :

La sortie du terminal indique que 98 dépendances ont été testées, que 3 problèmes ont été détectés et que 6 chemins vulnérables ont été identifiés, notamment des vulnérabilités d’exécution de code à distance (RCE) et de validation de certificats.

En résumé, lorsqu’une dépendance de votre application Spring Boot présente une vulnérabilité détectée par Snyk, procédez comme suit :

  • Mettez à jour la version générale de Spring Boot au lieu de mettre à jour un starter spécifique.

  • Lors de la mise à jour de Spring Boot, il ne suffit pas de mettre à jour les propriétés de version de ses dépendances.

  • Utilisez la gestion des dépendances dans Maven ou Gradle pour mettre à jour des dépendances transitives spécifiques.

Lancez-vous dans les compétitions Capture The Flag

Apprenez à résoudre des défis de capture du drapeau en regardant à la demande notre atelier virtuel d’initiation.

Lire la suite

Blog

Les modèles de pointe ont trouvé les vulnérabilités. Seul l’attaquant a trouvé les chaînes d’exploitation.

L’analyse statique a détecté les failles, mais seuls des tests d’attaque en conditions réelles ont prouvé comment elles pouvaient être enchaînées pour provoquer des compromissions. Comparaison d’Evo COS, de Claude Security et de Claude Code Security.

feature insights context
Blog

Les attaques autonomes sont déjà là. La défense doit suivre leur rythme.

Les attaquants autonomes réduisent la fenêtre de défense. Découvrez comment la découverte, la correction, la validation et la prévention continues peuvent aider les équipes de sécurité à suivre le rythme.

Blog

Pourquoi les agents de codage IA créent-ils sans cesse des failles de contrôle d’accès ?

Les agents de codage IA peuvent générer une logique d’autorisation qui compile et passe la revue, tout en exposant les données d’un tenant à un autre. Découvrez pourquoi les failles de contrôle d’accès sont difficiles à détecter et comment les prévenir.