You are on page 1of 10

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

PHP secure
> date de dernire modification : 08/03/2006

Le PHP est un langage moderne, puissant et, au regard de ses possiblits, relativement bien conu du point de vue de la scurit. Rappel des possibilits de PHP : interfaage de bases de donnes, traitement de formulaires, lecture / criture de fichiers, excution de commandes systme, ouverture / gestion de connexions rseaux, etc. Il est important de ne pas perdre de vue que les scripts sont excuts ct serveur -- serveur web qui plus est, donc par dfinition aussi "expos" que possible. Le but de cet article est de faire une synthse des "bonnes pratiques", en matire de scurit, dans l'criture de scripts PHP. Ce document sera mis jour aussi souvent que ncessaire, et profitera pleinement de vos remarques et suggestions. N'hsitez pas !

sommaire
pr-requis cgi ou sapi ? principes de base le fichier php.ini la faille include() les bases de donnes les sessions rfrences

pr-requis
Une bonne connaissance (au mieux une bonne pratique) du PHP, des bases de donnes et du Web sont ncessaires la bonne comprhension de cet article. Au besoin, on peut consulter mon ultra-concis PHP. Cela dit, le propos est ici d'tre le plus clair, le plus gnraliste, et, nous l'esprons, le plus didactique possible. Le lecteur est suppos galement avoir lu la partie consacre la scurit du manuel en ligne, que le prsent article se propose de complter.

1 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

Enfin, il n'est peut-tre pas inutile de rappeler que la scurisation des scripts PHP ne saurait se substituer la scurisation du serveur sur lequel ils tournent ! D'excellents logiciels libres ont t conus dans ce but (cf Scuriser un rseau htrogne avec des outils libres), n'hsitez pas les mettre en uvre...

cgi ou sapi ?
La compilation de PHP en tant que CGI (Common Gateway Interface) tant une pratique de plus en plus rare, nous redirigerons le lecteur vers la page du manuel consacr ce sujet. Par ailleurs, un manuel des "bonnes pratiques" dans l'criture des scripts CGI est disponible ici. Nous nous concentrerons donc ici sur l'utilisation, beaucoup plus rpandue, de PHP install en tant que module du serveur Web, ou SAPI (Server Application Programming Interface).

principes de base
Non, la scurit n'est pas (seulement) affaire de spcialistes. C'est l'affaire de tous, tout instant, depuis la conception du projet, jusqu' l'utilisation finale du programme et / ou service. Au-del de la technique pure, en constante volution, il s'agit d'acqurir les bonnes pratiques. L'ensemble de ces bonnes pratiques relve de la plus lmentaire prvention, sur laquelle on n'insistera jamais assez. Voici un florilge de principes essentiels garder en mmoire en toute circonstance (liste non-exhaustive) : veiller limiter au strict ncessaire les droits et permissions de l'utilisateur : il vaut mieux l'entendre se plaindre de son manque de libert plutt que de constater les dgts causs par une trop grande libralit (principe universel)

ne jamais faire confiance aux donnes transmises par l'utilisateur (encore moins l'internaute !), quand bien mme vous auriez lev les cochons ensemble...

toujours tester l'existence / la validit d'un fichier / code inclure : et s'il n'tait pas celui que vous croyiez ?

un contrle des donnes ct client est bien pratique, mais illusoire quant la scurit : quoi de plus simple que de dsactiver Javascript ? Seul un contrle ct serveur peut prtendre tre efficace. prfrer, quand cela est possible, la mthode POST la mthode GET : les variables dans l'url, a fait mauvais genre ;)

2 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/
prfrer, quand cela est possible, la mthode POST la mthode GET : les variables dans l'url, a fait mauvais genre ;)

ne pas confondre complexit et scurit : si votre systme de scurit vous chappe, considrez que vous n'tes pas en scurit. Bon, de toute faon, vous n'tes jamais en scurit.

s'efforcer de tenir jour systme serveur et interprteur PHP avec les dernires versions stables : quand la catastrophe aura eu lieu, ce sera a de moins vous reprocher...

le fichier php.ini
Que vous installiez PHP vous-mme ou que vous passiez par un hbergeur, la scurisation de vos scripts dpend pour une grande part de la configuration du fichier php.ini. Voici les diffrentes options de configuration concernes :

safe_mode Lorsque cette option est active ( safe_mode = on ) : - un certain nombre de fonctions sont limites ou dsactives (celles ddies aux commandes systmes, notamment). On trouvera ici une liste des fonctions affectes par l'activation du safe_mode.

- une vrification stricte des permissions d'accs des fichiers (bases sur l'UID et le GID) est faite sur les fonctions concernes.

- les variables d'environnement sont protges.

safe_mode_exec_dir Grce cette directive, il est possible de spcifier un ou plusieurs rpertoires dans lesquels les fonctions affectes par le safe_mode seront pleinement disponibles. exemple : safe_mode_exec_dir = /private_dir/.

safe_mode_allowed_env_vars

3 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

safe_mode_allowed_env_vars Seules les variables commenant par les prfixes cits ici peuvent tre modifies (par dfaut : safe_mode_allowed_env_vars = PHP_ et c'est trs bien comme a).

safe_mode_protected_env_vars Via cette directive, on peut fournir une liste des variables d'environnement quun script ne pourra jamais modifier (par dfaut : safe_mode_protected_env_vars = LD_LIBRARY_PATH).

disable_fonctions Comme son nom l'indique, cette directive permet de dsactiver les fonctions spcifies. Les noms de fonctions doivent tre spars par une virgule. Cette directive est indpendante du safe_mode. exemple : disable_functions = exec, system, passthru, popen, mail

open_basedir Cette directive (indpendante du safe_mode) limite les permissions d'accs aux seuls dossiers spcifis (la racine tant document_root), rcursivement. exemple : open_basedir = /pub_dir/

display_errors En phase de dveloppement, il est bon d'avoir le maximum d'infos sur ce qui pourrait nuire la bonne, et scure excution des scripts (variables et constantes non-dfinies, essentiellement). > donc : error_reporting = E_ALL En phase de production, il est sage de ne pas laisser ce genre de messages d'erreur s'afficher l'cran :

Warning: readfile() failed (No such file or directory) in /var/www/perso/confidentiel.php on line 356
> donc :

4 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

> donc : display-errors = off

log_errors Une fois active (log_errors = on), cette directive permettra la redirection des messages d'erreur (dont on a interdit l'affichage l'cran) vers les fichiers logs (unix), dans les journaux d'vnements (win), ou dans des fichiers spcifis dans la directive suivante :

error_log Permet de spcifier le fichier dans lequel seront crits les messages d'erreur. exemple : error_log = /var/php/logs/

register_globals Permet de rendre globales ou non les variables EGPCS (Environment, Get, Post, Cookie, Session). Il est vivement conseill de dsactiver cette directive (register_globals = off), ne serait-ce que pour s'obliger prendre les bonnes habitudes en utilisant les variables superglobales. Succinctement, les variables hrites des mthodes EGPCS ne seront plus disponibles telles quelles, mais accessibles seulement via les superglobales correspondantes.

<?php if (!$_SESSION['auth']) die ("Vous n'tes pas authentifi"); ?>

allow_url_fopen Permet de traiter les url comme des fichiers, d'o la porte ouverte des plaisanteries douteuses (cf la faille include()). En consquence : allow_url_fopen = off

magic_quotes_gpc

5 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

Cette directive permet d'chapper (par backslashes) les quotes, double quotes, backslashes et caractre NULL des chanes de caractres issues des mthodes Get, Post et Cookies. Rappelons que, pour pouvoir tre passs sous forme de requte SQL, ces caractres doivent tre chapps via la fonction addslashes(). A contrario, pour l'affichage d'une chane de caractres l'cran sans backslashes, on aura recours la fonction stripslashes(). La raison pour laquelle cette directive doit tre active ( magic_quotes_gpc = on ) est que les attaques par injection SQL (cf les bases de donnes) utilisent trs souvent les quotes non chappes. Bon article sur les magic_quotes : phpinfo.net/articles/article_magic-quotes.html.

magic_quotes_runtime Comme la prcdente, cette directive permet d'chapper les quotes, double quotes, backslashes et caractre NULL, mais des chanes de caractres provenant d'une ressource externe (base de donnes, zone de texte, etc). Pour les mmes raisons que prcdemment : magic_quotes_runtime = on .

include_path Spcifie le chemin des pages inclure : ne pas oublier de renseigner cette directive (cf la faille include()) ! exemple : include_path = /var/htaccessed_dir/

file_uploads Autorise l'upload de fichiers sur le serveur via un script PHP. A dsactiver, bien sr, si on n'en a pas besoin.

la faille include()
Cette faille a fait l'objet d'une littrature abondante, grce quoi elle a pratiquement disparu aujourd'hui. Le but du jeu consiste ne pas permettre n'importe qui d'inclure n'importe quelle page, que ce soit pour accder des donnes sensibles, ou pour simplement dfacer votre belle page d'accueil ;)

6 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

ou pour simplement dfacer votre belle page d'accueil ;) Outre la dsactivation de allow_url_fopen, qui interdira l'inclusion de fichiers distants, voici une manire trs simple de se prmunir :

<?php $filename = "./page.php"; if (file_exists($filename)) include($filename); ?>


une excellente mesure consiste regrouper les fichiers de bibliothques dans un rpertoire protg par .htaccess. Il est galement recommand d'viter de donner l'extension .inc aux fichiers inclure. En effet, si le serveur n'est pas configur pour interprter les fichiers avec cette extension, il est tout btement possible de les tlcharger ou, encore plus btement, que le code source s'affiche l'cran... Pas terrible :( Cela dit, si vous avez accs votre httpd.conf, il suffit de rajouter l'extension ".inc" ici :

AddType application/x-httpd-php .phtml .pwml .php3 .php4 .php .php2 .inc


Pas plus difficle que a. autre solution : ajouter une seconde extension... par exemple ".php" :

<?php $filename .= ".php"; ?>


> ou bien encore, toujours dans httpd.conf, interdire l'accs de tels fichiers :

<Files ~ ".inc"> Order allow,deny Deny from all Satisfy All </Files>
On le voit, les faons de se protger sont multiples et varies. L'essentiel tant de comprendre, comme toujours, la nature du danger.

les bases de donnes


De mme que scuriser ses scripts n'a pas grand sens si le systme ne l'est pas, il fortement conseill de bien connatre son SGBD, particulirement bien sr ses mcanismes de scurit. Le principal souci d'une bdd expose sur le web provient des injections SQL voques plus haut.

7 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

Sans rentrer dans des considrations avances, rappelons seulement que le principe de ce type d'attaque est de passer des requtes "imprvues" au SGBD, le plus souvent via les champs d'un formulaire, et grce l'emploi astucieux de caractres spciaux ("'", "%", "*", "#", etc). un exemple trs connu d'injection sql repose sur l'ide de "couper", l'aide de commentaires, une partie de la requte l'excution. Soit un banal formulaire d'identification :

<form method="post" action="auth.php"> login : <input type="text" name="login"><br /> password : <input type="password" name="password"><br /> <input type="submit" value="OK">
> et une requte, encore plus banale, utilisant les variables issues du formulaire :

$query = "SELECT * FROM users WHERE login = '".$_POST['login']. "' AND password = '".$_POST['password']."'";
Pour peu que le pirate connaisse un login "sensible" (sans en connatre le mot de passe), il pourrait essayer de renseigner ainsi le champ "login" du formulaire :

admin'#
> notre requte deviendrait alors :

$query = "SELECT * FROM users WHERE login = 'admin'#' AND password = 'jun40h'";
Ce qui a l'excution donnerait le produit de la requte SQL suivante :

SELECT * FROM users WHERE login = 'admin'


PHP ignorant tout ce qui se trouve aprs le signe '#' ne transmettra pas la dernire partie de la requte... Plus besoin de mots de passe ;)

Pour vous prmunir contre ces dsagrments, vous avez votre disposition tout un arsenal de fonctions qui vous permettent de filtrer (ou "parser") les donnes transmises pas l'internaute. > il est galement recommand de hasher (via md5()) logins et mots de passe avant de les stocker. Exemple :

<?php $login = trim(htmlspecialchars(addslashes($_SESSION['login']))); $password = trim(htmlspecialchars(addslashes($_SESSION['password']))); $query = "INSERT INTO clients VALUES (md5($login), md5($password))";
8 sur 10

// parsing du login // parsing du password // insertion des variables hashes


04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

$query = "INSERT INTO clients VALUES (md5($login), md5($password))"; ?>

// insertion des variables hashes

toute fin utile, rappelons qu'il est essentiel de crer un utilisateur de la base dont les droits seront restreints au strict minimum (lecture seule si possible). Si votre bdd contient des donnes rellement sensibles, le serveur doit tre configur pour supporter les connexions via SSL (Secure Socket Layer, www.openssl.org).

les sessions
L'usage des sessions est un moyen sr, simple, efficace et largement utilis de "tracer" ses visiteurs (sites de commerce en ligne, forums, etc). Le principe en est simple : il s'agit d'attribuer un identifiant unique chaque visiteur (par dfaut PHPSESSID), ce qui crera un fichier dans un rpertoire temporaire sur le serveur, fichier dans lequel seront stockes les variables gnres par la session. Il suffit alors d'appeler (avant tout affichage html) la fonction session_start() sur chaque page o l'on souhaite utiliser ces variables. Cela peut se faire de diffrentes faons : - automatiquement (via la directive session.auto_start), mthode dconseille.

- via un formulaire dont les champs renseigns seront filtrs : mthode conseille.

- en passant par le tableau superglobal $_SESSION pour la rcupration des variables : toujours.

- avec ou sans cookies, sachant que s'ils sont bien pratiques pour conserver les variables d'une session l'autre, les cookies peuvent tre refuss par le client :( L encore, un minimum de vigilance est requis, afin de protger chaque identifiant, et prvenir d'ventuelles usurpations d'identit. La premire mesure lmentaire prendre consiste stocker logins et mots de passe dans une base de donnes (et au besoin relire la section prcdente). une bonne ide est de rcuprer (via la variable superglobale $_SERVER['REMOTE_ADDR']) l'ip du visiteur, afin de garantir son caractre unique :

<?php

9 sur 10

04/02/2013 08:57

secure PHP

http://thierrylhomme.developpez.com/php/php_secure/

<?php if (isset($ip) && $ip == $_SERVER['REMOTE_ADDR']) { echo "Welcome home, $login !"; } else { header('Location: login.php'); } ?>

10 sur 10

04/02/2013 08:57

You might also like