OVH Cloud OVH Cloud

[Long] Pratiques de codage php et webapps

120 réponses
Avatar
John Gallet
Bonjour,


NB1 : xpost fr.comp.lang.php et fu2 fr.comp.securite (les deux sont
modérés).

Après moult tergiversations, je laisse le fu2 sur fr.comp.securite car
on dépasse le cadre du langage PHP et que les failles à débattre sont
majoritairement
humaines et non liées au langage. J'encourage plus que vivement les
habituels lecteurs/contributeurs de fclphp à suivre la discussion sur
fcs (et à le
consulter régulièrement une fois cette bonne habitude prise ;-)...)

Je me porte volontaire pour essayer de faire une synthèse de la
discussion qu'on pourra intégrer dans l'une des deux FAQs et référencer
depuis l'autre.

NB 2 : Cet article étant long et fcs étant modéré, je rappelle aux
contributeurs qui seraient tentés de le citer intégralement que leur
réponse n'a aucune chance d'être publiée. Si vous avez un doute sur la
bonne manière de répondre sur un forum usenet, usez et abusez de
http://www.giromini.org/usenet-fr/repondre.html


Suite aux divers questions/trolls sur la sécurité des applications
écrites en PHP dans une optique web, je lance un petit débat sur les
pratiques de codage en PHP apportant ou non un vrai "plus" de sécurité.

J'entends par "faille de sécurité" une erreur de codage ou de conception
qui permet de passer outre une procédure d'authentification, d'avoir
accès à des données non publiques, ou de modifier/détruire des
données/des scripts, exclusivement dans une optique web, avec php comme
langage dans mon esrit à l'origine, mais on pourra élargir à d'autres
langages/plateformes de web dynamique comme perl, jsp, asp, .net etc...

Les questions sont les suivantes :

Question 1 :

Quelles sont les principales failles existantes dans les scripts PHP que
vous avez rencontrées ? Quels risques induisaient-elles ? Comment les
avez vous corrigées ?

Question 2 :

Quelles sont les principales fausses vérifications de sécurité que vous
connaissez ? Comment peut-on les contourner (indiquer la difficulté
pour y arriver) ou pourquoi ne sont-elles pas fiables ou non applicables
sur le principe même ?

Question 3 :

Pensez vous à des failles théoriques potentielles que vous n'avez pas
encore vérifiées en pratique ?

------------
Je commence bien entendu :

Question 1 (failles existantes):
a) variables non itilialisées en register_globals=On (injection de
variables)
Risque : principalement accès non autorisés, mais tout est possible.
Correction : initialiser ses variables (Sans blague...), ou utiliser des
fonctions/des objets car ils snt insensibles à l'injection de variables.
Piège : croire qu'on est toujours en register_globals=Off et coder comme
un cochon.
Correction : idem.

b) include dynamiques (ex include($toto);)

Risque : exécution sur sa machine de n'importe quel code souhaité par
l'attaquant (installation de back-doors, défigurations, etc....
Correction : ne pas utiliser d'includes dynamiques ou vérifier que le
fichier est bien local si hébergement dédié. Renforcer les restrictions
d'include_path. Attention, depuis php5, file_exists peut éventuellement
renvoyer TRUE sur des fichiers distants (à restester, je n'ai pas poussé
plus loin que le "tip php5" du manuel).
Piège : essayer de se renforcer avec include($toto.'.php');
Contournement : $toto="[target]/script_sans_extension"; par exemple.

c) injection SQL.
Risque : accès non autorisés, corruption de données
Correction : filtrage des variables, échappement de ' et " par le
caractère ad hoc pour la base de données (\ pour mysql, ' pour sybase
etc...)

d) confiance dans les variables venant de l'extérieur. Par exemple,
recalculer une facture à payer en utilisant un prix transmis par un
champ HIDDEN ou calculé en javascript. Ne pas revalider la donnée parce
qu'elle l'a été en JavaScript.
Risque : multiples. Accès non autorisés, corruption de données, etc...
Correction : ne faire confiance qu'à des données conservées côté serveur
(refaire une requête sgbd pour obtenir le prix de l'article, les frais
de port, etc...). Faire avant tout les validations de cohérence des
données côté serveur et non en javascript.

e) uploads de fichiers.
Outre les failles du langage php lui même qui apparaissent parfois à ce
sujet, les tutoriels que j'ai vus n'insistent pas assez sur le besoin de
faire attention aux extensions autorisées par rapport aux extensions
parsées sur le serveur. Si le serveur considère comme du code php le
fichier toto.php.txt, il faut interdire tout nom de fichier contenant
.php. dans son nom. Ceci doit venir en complément d'une liste
restrictive d'extensions explicitement autorisées (.jpg, .gif, .doc
etc...). Je suis plus particulièrement intéressé sur ce point par les
vérification purement serveur permettant de vérifier le type de fichier
traité.

f) utilisation de header("Location:...)
Algo (erronné)
1. vérification de cohérence
2.1 si problème alors header("Location:bad.php"); // jusqu'ici tout va
bien
2.2 si ok alors header("Location:ok.php"); // et plouf dommage, il
suffit d'appeler directement ok.php avec n'importe quels arguments et
tout passe.
Correction :
2.1 si problème require('erreur.php'); exit();
2.2 (sinon) require('traitement.php'); // rappel : toute variable locale
est alors définie dans traitement.php

g) appels systèmes non filtrés
Dans le même genre que les includes dynamiques, passer directement la
saisie de l'utilisateur à exec() ou system(). Personnellement, j'ai
tendance à interdire tout exécution de code directe, filtrée ou par (je
remplace les actions possibles par des cases à cocher et j'exécute ce
qu'il faut). Peut-être est-ce par trop parano et que 'lon peut autoriser
certaines choses.
Risques : donner la main sur votre machine à un attaquant.
Correction : ne jamais passer quoi que ce soit qui vient de l'extérieur
en argument, mais c'est parfois trop restrictif.

Question 2 (fausses vérifications):

a) vérifier que la donnée a bien été transmise par la méthode POST sous
prétexte qu'elle vient d'un formulaire.
Contournement : il suffit d'envoyer une donnée vérolée par post, que ce
soit en modifiant du html ou en utilisant la librairie CURL par exemple
pour de l'attaque massive. C'est le contenu de la donnée qu'il faut
vérifier, pas son mode de transmission.

b) Vérifier que les données viennent bien "de mon site" en utilisant
HTTP_REFERRER.

Une idée (qui n'est pas de moi) et que je n'ai pas réussi à mettre en
oeuvre : injection SQL par des entiers ou plus généralement injection
SQL insensible aux habituelles vérifications sur les quotes.

Soit la requête : "UPDATE .... WHERE id=$i " avec id de type entier
(typiquement : autoincrement)
But de la manip : injecter dans $i une chaîne transformant la requête en
(par exemple):
"UPDATE ... WHERE id=0 OR 1=1"
(requête qui va corrompre les données en impactant tous les rangs de la
table)
Moyen sous mysql : utiliser la fonction mysql CHAR et complèter la
chaîne en hexa. Mais je n'ai pas réussi à le faire, je me prends ou du
syntax error ou une chaîne non interprêtée.

Espérant faire avancer le shimili... le shcibi... le biniou.

JG

10 réponses

Avatar
Nicolas George
Nicob wrote in message
:
Il existe une technique tout bête permettant d'empêcher l'utilisation
d'un identifiant de session volé par XSS ou Referrer : dériver cet
identifiant de l'adresse IP du client, et rendre le cookie inutilisable si
pas utilisé depuis la bonne IP.


Mais dans ce cas, le site devient inutilisable depuis un site faisant du NAT
sur plusieurs adresses IP publiques sans s'assurer d'une certaine constance
des adresses apparentes, ou bien depuis un site utilisant plusieurs proxys
et répartissant la charge.

Avatar
Nicob
On Tue, 23 Nov 2004 09:11:46 +0000, John Gallet wrote:

Même si je prêche aussi la séparation "définir-faire", il n'est pas
toujours pratique de le faire (exemple typique : les templates
d'affichage appelés par le "vrai" code de logique).


A mettre au dessus de la web-root ou à protéger par .htaccess !

Si tu as une fonction ou un script autonome qui fait ça, un bon coup de
grep limite la casse.


Je parlais d'un audit fait en black-box, c'est-à-dire en accédant le
site avec un navigateur plutôt que par analyse du code source. Et dans ce
cas là, c'est vraiment galère à tester ...


Nicob

Avatar
Patrick Mevzek

Nicob wrote in message
:
Il existe une technique tout bête permettant d'empêcher l'utilisation
d'un identifiant de session volé par XSS ou Referrer : dériver cet
identifiant de l'adresse IP du client, et rendre le cookie inutilisable
si pas utilisé depuis la bonne IP.


Mais dans ce cas, le site devient inutilisable depuis un site faisant du
NAT sur plusieurs adresses IP publiques sans s'assurer d'une certaine
constance des adresses apparentes, ou bien depuis un site utilisant
plusieurs proxys et répartissant la charge.


Et même depuis un pauvre client en RTC (ou en ADSL) dont l'IP change
après déconnexion/reconnexion.

On ne peut pas utiliser l'IP comme validant fort.

On peut faire des tests mais c'est à pondérer.
Certains sites web permettent de ``régler'' le niveau de ``sécurité'' en
choisissant (pour un client donné à un moment donné donc) si le test doit
être fait sur la persistance de l'IP pendant toute la session.
Ca donne le contrôle à l'utilisateur... s'il comprend ce que cela
signifie bien entendu.

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>


Avatar
Patrick Mevzek

Il existe des mécanismes (librairie Pear) permettant a chaque requete de
changer dynamiquement et de maniere transparente la clé attendue pour la
prochaine requete. C'est tres pratique et assez sécurisant ...


Je ne sais pas comment la bibliothèque en question travaille, mais, s'il
est bon de changer régulièrement les identifiants de session au cours de
la navigation, voire à chaque requête, cela peut poser un problème si
l'application ne conserve que le dernier numéro.

En effet, si l'utilisateur utilise la touche 'Back' a priori, il revient
sur un identifiant précédent, que l'application va donc refuser.

Quant à stocker tous les identifiants pour une session donnée, et
chercher systématiquement dans cette liste, ca peut être couteux tant en
stockage qu'en calcul.

Il y a cependant je pense moyen de concilier les deux en ayant un
identifiant qui change à chaque requête mais qui reste compatible avec
l'usage du bouton Back. Cela complexifie la partie gérant les
identifiants de session, mais ca me parait possible, avec quelques outils
de base de crypto.

On a aussi des personnes qui préfèrent vérifier très strictement le
chemin suivi par l'utilisateur. Si l'utilisateur est sur la page X,
l'application sait que de là il ne peut aller que sur la page A, B et Z
en suivant les liens/formulaires présents dans la page X, et donc à la
requête suivant celle de la page X, l'application vérifie que ce qui est
demandée est soit A, B ou Z, et refuse tout le reste. Cela résout le
problème de vol d'identifiant de session a priori.

Cela me parait trop contraignant, car cela empêche en particulier d'être
connecté simultanément sur le site depuis plusieurs fenêtres (ou
onglets), sauf à s'authentifier séparément plusieurs fois, si tant est
encore que l'identifiant de session est dans l'URL et pas dans le cookie,
car dans ce dernier cas on ne peut pas vraiment être authentifié
plusieurs fois en même temps depuis la même machine.

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>

Avatar
Nicob
On Tue, 23 Nov 2004 23:10:07 +0000, Patrick Mevzek wrote:

On ne peut pas utiliser l'IP comme validant fort.


Un peu radical comme point de vue :)

Dans certains contextes, il est préférable que les personnes changeant
d'IP aient à se reconnecter plutôt que de risquer un vol de session si
un cookie est divulgué. Une étude de risques permettra de garantir que
les mesures prises restent proportionnelles au risque encouru ...


Nicob

Avatar
Simon Marechal
Fabien LE LEZ wrote:
On 22 Nov 2004 20:48:20 GMT, Laurent Seguin :


Seulement en demandant directement l'adresse dans un brouteur :
http://lesitedesadmins.tld/fichier_super_secret.ext, Pouf pouf les données
s'affichent.



Et c'est un fichier dont le nom est difficile à trouver ?


Et on le rajoutera dans robots.txt :) (oui ça arrive)


Avatar
Simon Marechal
Nicob wrote:
Un peu radical comme point de vue :)

Dans certains contextes, il est préférable que les personnes changeant
d'IP aient à se reconnecter plutôt que de risquer un vol de session si
un cookie est divulgué. Une étude de risques permettra de garantir que
les mesures prises restent proportionnelles au risque encouru ...


Le "problème", comme je l'ai découvert hier, ce sont les gens qui
utilisent des proxys "d'anonymisation" qui tournent toute les secondes.
Pour eux impossible d'utiliser le site. Vous me direz, bien fait pour eux :)

Avatar
Th. Boudet
Nicob wrote:

On ne peut pas utiliser l'IP comme validant fort.


Dans certains contextes, il est préférable que les personnes changeant
d'IP aient à se reconnecter plutôt que de risquer un vol de session si


Avec le navigateur intégré d'AOL 8, le changement d'IP a parfois
lieu à chaque requète: une page et quatre images = 5 IP.
Je suppose qu'il passe par un proxy sur le reseau AOL.


Avatar
Patrick Mevzek
On ne peut pas utiliser l'IP comme validant fort.


Un peu radical comme point de vue :)


J'aimerais bien que ce ne soit pas le cas, et qu'on puisse le faire.
Cependant, dans la pratique, on ne peut pas.

Dans certains contextes, il est préférable que les personnes changeant
d'IP aient à se reconnecter plutôt que de risquer un vol de session si


Pour certaines personnes, cela veut dire se reconnecter à chaque requête,
donc au final ne rien pouvoir faire.

C'est peut être un pourcentage minimal, mais si vous voulez une
application utilisable par tout le monde, comme ce n'est pas un
pourcentage nul, c'est déjà un problème.

Donc la pérennité de l'IP pendant la session peut être testée, mais si
vous basez la décision uniquement sur ca, vous aurez des problèmes...

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>


Avatar
Sylvain Tertois
Nicob a écrit:
On Tue, 23 Nov 2004 23:10:07 +0000, Patrick Mevzek wrote:

On ne peut pas utiliser l'IP comme validant fort.


Un peu radical comme point de vue :)

Dans certains contextes, il est préférable que les personnes changeant
d'IP aient à se reconnecter plutôt que de risquer un vol de session si
un cookie est divulgué. Une étude de risques permettra de garantir que
les mesures prises restent proportionnelles au risque encouru ...


A mon bureau on passe par plusieurs proxy, et mon adresse IP vue par le serveur
eut varier d'une page à l'autre. J'ai plusieurs sites que je ne peux pas voir
cause d'une politique de sécurité qui prend en compte l'adresse IP. Le pire
étant les sites sur lesquels il faut passer par 3-4 pages pour s'enregistrer,
avec la session qui saute avant d'arriver à la fin.

Par exemple pour m'enregistrer sur le site de Texas Instruments j'ai dû
recommencer 4-5 fois. Sur le site de Fairchild Semiconductors j'ai jamais
réussi, j'ai dû le faire depuis chez moi...
Donc un site qui utilise l'IP comme validant fort, ça me gonfle! ;-)


--
Sylvain