Skip to main content

Exploration du contournement d’autorisation dans Spring Security (CVE-2022-31692)

Écrit par
feature spring security auth bypass

16 décembre 2022

0 minutes de lecture

Début novembre, une nouvelle vulnérabilité de contournement d’autorisation a été découverte dans Spring Security 5. Avant de céder à la panique, examinons ce problème pour déterminer si vous êtes concerné. Bien que la vulnérabilité soit classée comme élevée, seuls certains cas d’utilisation précis sont vulnérables. Cela signifie que tout le monde n’est pas concerné, comme je vais le montrer dans un instant. Quoi qu’il en soit, il est recommandé de passer à une version plus récente de Spring Security, à savoir la version 5.6.9 ou ultérieure, ou la version 5.7.5 ou ultérieure.

Qu’est-ce qu’un contournement d’autorisation ?

En gros, son nom est très explicite. Imaginons qu’une page Web de notre application Spring Boot soit accessible uniquement aux utilisateurs auxquels le rôle d’administrateur a été attribué. Un contournement d’autorisation signifie qu’un utilisateur qui n’est pas administrateur pourrait accéder à cette page dans certains cas d’utilisation sans disposer de ce rôle (ou d’un rôle supérieur). Ce n’est évidemment pas souhaitable et cela peut entraîner divers problèmes, notamment des fuites de données et la modification, la création ou la suppression non autorisées de données.

Comment fonctionne ce contournement d’autorisation dans Spring Security ?

Avec Spring Security, il est possible de créer une SecurityFilterChain pour définir les autorisations de points de terminaison spécifiques. Dans les versions récentes de Spring, cela ressemble à ceci :

@Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  http
     .authorizeHttpRequests((authorize) -> authorize
        .antMatchers("/").permitAll()
        .antMatchers("/forward").permitAll()
        .antMatchers("/admin").hasAuthority("ROLE_ADMIN")
        .shouldFilterAllDispatcherTypes(true)
     )
     .httpBasic().and()
     .userDetailsService(userDetailsService());
      return http.build();
  }

Dans l’exemple ci-dessus, j’ai utilisé antMatchers pour définir les autorisations des modèles d’URL, indépendamment de la méthode HTTP. Tout le monde peut accéder à / et à /forward. Seuls les utilisateurs ayant le rôle d’administrateur peuvent accéder à l’URL /admin.

Jusqu’ici, tout va bien. Rien de compliqué, et tout fonctionne parfaitement. Examinons maintenant l’implémentation du point de terminaison forward dans mon contrôleur.

@GetMapping("/forward")
public String redirect() {
  return "forward:/admin";
}

Dans l’implémentation ci-dessus, le point de terminaison forward transfère la requête au point de terminaison admin. J’ai également ajouté tous les types de dispatcher à ma configuration Spring Security, car par défaut seuls request, async et error sont pris en charge. J’ai ajouté la ligne suivante au fichier application.properties de mon application Spring Boot.

spring.security.filter.dispatcher-types = request, error, async, forward, include

Vous pourriez penser que tout est en ordre et que le point de terminaison admin est bien protégé par les filtres. Pourtant, je peux désormais accéder au point de terminaison admin via /forward, sans avoir le rôle d’administrateur ni même me connecter. Même si nous avons explicitement ajouté forward à notre configuration et activé shouldFilterAllDispatcherTypes(), nous pouvons toujours accéder à la page d’administration. En utilisant forward et en incluant tous les types de dispatch, il est possible de contourner l’autorisation et d’accéder à un point de terminaison protégé par des privilèges supérieurs.

Fenêtre du navigateur à l’adresse localhost:8080/forward affichant le texte « This is the Admin page »

Cela est possible dans Spring Security 5 parce que, par défaut, les filtres ne s’appliquent qu’une seule fois à une requête. Les utilisateurs doivent donc configurer explicitement Spring Security pour qu’ils s’appliquent plusieurs fois. En outre, le FilterChainProxy n’est pas non plus configuré pour être invoqué lors des types de dispatch forward et include.

Le problème se produit également dans les anciennes versions de Spring Security 5

Si vous utilisez une ancienne version d’une application Spring, vous disposez probablement aussi d’une ancienne version de Spring Security. Une ancienne application Spring Boot que je maintiens pour des ateliers repose sur la version 2.2.0-RELEASE, fournie avec Spring Security 5.2.0-RELEASE. Dans ces anciennes versions, la configuration de la sécurité était un peu différente. Il fallait créer une classe de configuration étendant l’interface WebSecurityConfigurerAdapter et redéfinir la méthode configure() pour implémenter des filtres similaires à ceux mentionnés précédemment.

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
               .authorizeRequests()
               .antMatchers("/").permitAll()
               .antMatchers("/forward").permitAll()
               .antMatchers("/admin").hasAuthority("ROLE_ADMIN");
   }
}

Dans l’exemple ci-dessus, nous avons reproduit une vulnérabilité similaire à la précédente. En résumé, nous utilisons la même chaîne de filtres, celle où le problème se produit.

Quelle est la gravité de ce problème dans Spring Security ?

Comme toujours, tout dépend de votre utilisation. Bien que CVE-2022-31692 obtienne un score de 9,8 (critique) selon la National Vulnerability Database (NVD), Snyk lui attribue un score légèrement inférieur de 7,4, ce qui en fait une vulnérabilité de gravité élevée.

Bien que cette vulnérabilité soit assez facile à exploiter et largement accessible, seuls certains cas d’utilisation précis sont réellement vulnérables. Si vous utilisez les types de dispatch forward et include, ainsi que les AuthorizationFilters comme dans les exemples ci-dessus, vous pourriez être concerné. Si, dans ces types de dispatch, vous appelez un point de terminaison disposant de privilèges supérieurs et que vous utilisez le AuthorizationFilter pour définir les privilèges, cela peut effectivement entraîner un contournement d’autorisation.

Cela signifie qu’un grand nombre de conditions doivent être réunies pour que vous soyez réellement affecté par cette vulnérabilité. Pour obtenir la liste complète, consultez notre avis sur ce problème de sécurité dans la Snyk Vulnerability Database.

Comment remédier à ce problème de sécurité

La solution la plus simple et la plus efficace consiste à mettre à jour Spring Security vers la version 5.7.5 ou ultérieure. Si vous utilisez encore la branche 5.6.x, le problème est corrigé dans la version 5.6.9. Si vous travaillez avec une application Spring Boot, la meilleure option consiste à passer à Spring Boot 2.7.6 (ou à une version ultérieure), qui inclut automatiquement la version appropriée de Spring Security si vous utilisez cette fonctionnalité.

Si vous ne pouvez pas effectuer la mise à jour, vous pouvez remplacer la définition de votre filtre authorizeHttpRequests().shouldFilterAllDispatcherTypes(true) par .authorizeRequests().filterSecurityInterceptorOncePerRequest(false). Le type de dispatch forward sera ainsi filtré comme prévu.

En reprenant le premier exemple de cet article, la correction se présente ainsi :

@Configuration
public class SecurityConfig {

   @Bean
   public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
       http
               .authorizeRequests()
               .filterSecurityInterceptorOncePerRequest(false)
               .antMatchers("/").permitAll()
               .antMatchers("/forward").permitAll()
               .antMatchers("/admin").hasAuthority("ROLE_ADMIN")
               .and()
               .httpBasic().and()
               .userDetailsService(userDetailsService());
       return http.build();
   }
}

De la même manière, nous pouvons ajouter .filterSecurityInterceptorOncePerRequest(false) à l’ancienne définition d’un filtre, qui nécessitait d’étendre WebSecurityConfigurerAdapter.

Mettez à jour vos dépendances pour rester en sécurité

Cela montre une fois de plus qu’il est essentiel de maintenir vos dépendances à jour. Lorsqu’un problème de sécurité comme celui-ci affecte votre application et que vos dépendances sont obsolètes, sa résolution vous demandera beaucoup plus d’efforts. Grâce aux fonctionnalités d’analyse SCA, comme celles de Snyk Open Source, vous obtenez ces informations et des conseils de correction dès qu’ils sont disponibles. Vous pouvez utiliser Snyk gratuitement. Pour vous aider à démarrer avec le développement Java, j’ai écrit un article simple sur les premiers pas.

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.