SecurityInsider
Le blog des experts sécurité Wavestone

SerializationGate : le coup d’arrêt porté à la sérialisation… qui met à mal de nombreux serveurs applicatifs (WebLogic, JBoss, Jenkins, etc.)




Janvier 2015, lors de la conférence AppSecCali, Chris Frohoff et Gabriel Lawrence présentent leurs travaux [1] sur les possibilités d’exécution de commandes suite à la désérialisation d’objets de certaines bibliothèques chargées par la JVM (le fameux CLASSPATH)…

En novembre 2015, Stephen Breen s’empare du sujet pour lui donner un impact d’envergure : il découvre que ces bibliothèques sont chargées dans des serveurs applicatifs qui utilisent nativement la sérialisation/désérialisation (WebLogic, JBoss, etc.) et qu’il suffit alors d’envoyer une requête, pour leur faire exécuter du code…
Et depuis, le sujet ne fait pas beaucoup parler de lui… pourtant, il soulève de nombreuses problématiques :
Quand on connait les difficultés pour avoir un parc de serveurs applicatifs à jour, comment gérer les bibliothèques utilisées par les applicatifs, les développements, etc. ?
Même en corrigeant les bibliothèques identifiées, d’autres (bibliothèques tierces, internes, etc.) pourraient présenter ces failles !
Au-delà de ces premières interrogations, c’est le mécanisme même de la sérialisation/désérialisation qui est remis en cause. Dans un article de son blog [2], la Fondation Apache écrit : « The best protection against this, is to avoid using a complex serialization protocol with untrusted peer ». No comment ;-)

Rappel des faits

La sérialisation est un mécanisme qui permet de rendre un objet persistant à des fins :
  • De stockage : l’objet peut alors être rechargé depuis un fichier, une base de données, etc.
  • De transmission : une application A peut directement transmettre l’objet à une application B.

En Java, tout objet implémentant la classe « Serializable » ou « Externalizable » ou définissant les méthodes « readObject », « readResolve » ou « readExternal » peut être manipulé de la sorte.
Et c’est ces méthodes, « readObject », qui sont appelées par la JVM avant même que l’application puisse contrôler le contenu de l’objet, source de cette problématique !
En effet, si l’application A attend un objet sérialisé qui autorise, par cette méthode, la réalisation d’actions dangereuses, alors ces dernières seront exécutées par la JVM et à l’insu de l’application A.
Les travaux de Chris Frohoff et Gabriel Lawrence ont montré comment un objet de la bibliothèque « Apache Commons Collections » (« Transformer ») pouvait être manipulé dans ce sens. Il rend possible la transformation d’un objet en spécifiant la classe utilisée pour l’opération. En l’occurrence, « Runtime.Exec », bien connu des pentesters pour permettre l’exécution de commande système.
Si la bibliothèque « Apache Commons Collections » est chargée par la JVM (autrement dit, présente dans son CLASSPATH), alors l’application A va charger l’objet, le lire… et exécuter la commande système !
Notons que ce type de faille a été exploitée dans cette bibliothèque, mais qu’elle est également présente dans d’autres (Spring, Groovy et d’autres à découvrir).

Et concrètement ?

En reprenant cette découverte (jusqu’alors passée sous silence), Stephen Breen a remarqué :
  1. Que cette bibliothèque était inclue par défaut dans de nombreux serveurs applicatifs : WebLogic, JBoss, Jenkins, etc.
  2. Que ces composants manipulaient nativement des objets sérialisés :
  •  WebLogic sur les flux T3 ;
  •  JBoss et Jenkins sur des flux HTTP.
Dans le pire des cas, la manipulation des objets est réalisée avant authentification (puisque l’authentification repose elle-même sur l’envoi d’un objet sérialisé) : une simple requête permet l’exécution de code sur un serveur WebLogic activant le protocole T3 (ou T3S).
De manière globale, tous composants manipulant des objets sérialisés et en capacité de charger une classe vulnérable sont sujets à cette faille :
  • Serveurs applicatifs évoqués ;
  • Serveur d’un applet ou d’un client lourd Java communiquant par objets sérialisés ;
  • Composant exposant une interface RMI (Remote Method Invocation).
Si certains de ces services n’ont pas à être exposés de toute manière sur Internet, il n’en est clairement pas de même sur un réseau interne ou entre serveurs de zones de confiance très différentes.

Mais que faire alors ?

C’est surement dans la remédiation à cette faille que réside la plus grande problématique… Car pour un applicatif utilisant ces principes, la désactivation du protocole T3 [3] (comme recommandé actuellement en solution de secours pour WebLogic) n’est clairement pas envisageable.
La suppression ou la mise à jour des bibliothèques sujettes à ces failles ne représente pas une solution pérenne : d’autres failles dans d’autres bibliothèques seront découvertes…
À l’heure actuelle, une solution [4] possible consiste à surcharger la méthode  « resolveClass() » de « java.io.ObjectInputStream » afin de créer un filtre personnalisé limitant les désérialisations à une liste blanche. Mais cette solution demande des développements et recettes non négligeables.
L’exploitation de cette faille conduira peut-être à l’intégration de limitation au sein de la JVM, qui serait le meilleur compromis… reste à attendre les mises à jour...

Sources :
[1] https://frohoff.github.io/appseccali-marshalling-pickles/
[2] https://blogs.apache.org/foundation/entry/apache_commons_statement_to_widespread
[3] http://www.oracle.com/technetwork/topics/security/alert-cve-2015-4852-2763333.html?evite=WWSU12091612MPP001
[4] http://www.ibm.com/developerworks/library/se-lookahead/
Yann FILLIAT

Aucun commentaire:

Enregistrer un commentaire