[PHP] Sécurité: Cross-site request forgery (CSRF)


[PHP] Sécurité: Cross-site request forgery (CSRF)


Comment sécurisez son code contre les attaques CSRF

  Kessako ?
===========

Cross-Site Request Forgery (CSRF ou XSRF), aussi appelé pour le fun Sea Surf. Ce type d'attaque à l'opposé du XSS exploite la confiance qu'a un site envers ses utilisateurs.
L'utilisateur devient, malgré lui, complice de l'attaque (contrairement à XSS où il est la victime).

En gros elle consiste à injecter des données sur le site afin de faire effectuer des actions par un utilisateur normal lambda. Un utilisateur qui peut avoir certaines fonctions/droits (possibilité de créer un nouveau forum par exemple).
Le principe est simple: il suffit d'arriver à mettre du code (généralement HTML) quelque part (forum, email, MP, images,...).

- Et PHP ?
===========
Comme XSS, ce genre d'attaque n'a rien à voir avec le type de langage utilisé.
Les méthodes de protection sont donc souvent les mêmes. Par contre, les attaques CSRF ne sont pas aussi fréquentes que les attaques SQL Injection ou XSS, elles sont plus dangereuses car plus difficile à contrer.

- Par pratique :
===============

L'un des exemples les plus simple/frequent est celui des forums.
C'est souvent l'endroit le plus vulnérable. Chacun peut y poster ses messages et ses images.

Le plus dangereux ce sont les images, en effet très souvent (pour ne pas dire toujours), elles sont automatiquement ouvertes/lues par le navigateur.

L'utilisateur d'un forum fourni souvent un avatar en forme d'url vers l'image à afficher à côté de chacun de ses posts. Cette image est, sur pas mal de site, une image se trouvant à l'extérieur du site.

Pour l'instant tout parait normal/légitime, mais vous allez découvrir que ça peut cacher des énormes risque de sécurité.

Prenons donc un forum à l'adresse forum.machin.truc.
Avec un script qui s'occupe de créer un nouveau topic qui s'appelle topic_new.php :
<?php
require_once 'forum_lib.inc.php';
if (!empty($_GET['envoyer']) && $utilisateur->PossedeDroit('topic','creation'))
$forum->ajouterTopic($_GET['topic']);
?>


le formulaire de création de topic étant le suivant :

<form action="topic_new.php">
nom du topic: <input type="text" name="topic"/>
<input type="submit" value="Créer"/>
</form>

un utilisateur malveillant, qui veut par exemple créer un nouveau forum, poura poster un message genre :

j'ai decouvert un site genial, <a href="http://forum.mahin.truc/topic_new.php?topic=porno"> decouvrez le ici</a>. ca roxe !

Vous me direz faut vraiment être con pour cliquer sur le lien.
Souvenez-vous qu'il y a toujours des noobs partout avec des accès admin, même les plus experimentés se font avoir parfois (on verifie toujours pas le lien qui se cache derrière une url quand on l'ouvre).

Un code genre :
<a href="http://forum.mahin.truc/topic_new.php?topic=porno">http://site.legal.com</a>

ou encore avec un bout de javascript genre

<a href="http://forum.mahin.truc/topic_new.php?topic=porno" onmouseover="window.status='http://site.legal.com'">

et vous voila tombé dans le piege ;)

Mais partant dans un raisonnemnt plus draconien, on est sur un forum qui n'autorise pas le code HTML, et qui utilise que du BBCode, et que tous les admins sont des roxeurs de la mort qui tue :)

Vous vous souvenez j'avais parlé des images tout à l'heure.
Mais avant de dévoiler l'attaque, je détaille un peu qu'est ce qui se passe dans un navigateur quand je met une image
en avatar genre [url]http://monsite.blabla/monimage.jpg[/url].

quand je demande à lire un post (getpost.php?id=42 par exemple) contenant un message du l'utilisateur ayant l'avatar, le navigateur récupère la page avec une requete HTTP au serveur.

La requête ressemble à un :
GET /getpost.php?id=42

une fois la page récupérée, le brouteur (à la frenchy ;) ) lit et analyse le HTML et se contruit une liste des éléments externes (images, videos, ..etc)
puis effectue une requête pour récupérer ces éléments, soit la requête HTTP suivante :
GET /image_forum.png
dans le cas d'une image sur le même serveur.
et établie une connexion vers les autres serveurs externes (dans notre exemple le serveur "monsite.blabla") et refait une requete HTTP pour récupérer l'élément dont il a besoin, donc dans notre cas.
GET /monimage.jpg

Maintenant imaginons qu'a l'url de l'image je met
[url]http://forum.mahin.truc/topic_new.php?topic=porno[/url]

ou encore plus marrant ;)
[url]http://forum.mahin.truc/poster_message.php?topic=porno&msg=je%20suis%20un%20pedophile%20nazi%20et%20je%20vous emmerde[/url]

Suffit qu'un admin ouvre le post, et le topic sera crée (ou le message envoyé, gniark ]:) ) et ca sera logué comme venant de sa part :D. Il remarquera même pas qu'il a fait ça, car à la place de l'avatar il n'y aura rien d'affiché (sous firefox) ou un X à la place sur IE.

En fonction de l'url et du type du site/utilisateur les dégats peuvent être plus dangereux.
Exemple :
[url]http://sitecommercetresconnu.com/unClickPourAchater.php?itemid=58475&livraison=adresse%20postal%ou%20recupere%20le%colis[/url]


- et la solution ?
==================


-Si vous codez votre propre forum/system de messagerie, utilisez des envois par POST au lieu de celle par default (GET) :
<form action="topic_new.php" method="post">
- désactivez les register_globales si possible et n'utilisez que la variable $_POST (après vérification bien sûr).
- désactivez les fonctionnalités qui sont pas vraiment nécessaires (avatar, image, url...).
- Pour les avatars préviligiez une liste d'images stockéz sur le site, avec, si besoin, possibilité d'ajouter une image apres modération.
- Pour les images rajoutez dans la mesure du possible un test pour vérifier si c'est vraiment une image. En utilisant par exemple la fonction php getimagesize():

if (getimagesize($url)===FALSE)
die("image invalide !");

- Utilisez des tokens (numéros aleatoires générés à chaque passage sur le site (ou une parti sensible du site)) sur les formulaires, et stocker les en plus dans les sessions et/ou cookies.

<form action="topic_new.php">
nom du topic: <input type="text" name="topic"/>
<input type="hidden" name="token" value="<?php echo md5(uniqid(rand(), true)); ?>" />
<input type="submit" value="Créer"/>
</form>

<?php
require_once 'forum_lib.inc.php';
session_start();
if (array_key_exists('token',$_SESSION)) {
if (array_key_exists('topic',$_POST) && array_key_exists('token',$_POST) && ) {
if ($_POST['token'] == $_SESSION['token']) {
// Code pour verifier les droit, le nom du topic
// code pour créer le topic
} else {
// code pour Loguer le cracker
// et le REFERER pour voir d'ou vien l'attaque
}
} else {
// code pour loguer le fucking lamer :p
}
} else {
// Session expiré ?
}
?>

- Pour toutes les operations importantes/d'admin, utilisez plusieurs ecrans (au moins deux pages: une page formulaire + une page de confirmation, mais jamais un click = une action).


Pour résumer, on le dira jamais trop, il faut toujours filtrer les données externes. Soyez plus futés que les crackers/pirates.

A vos commentaires.

Happy Hacking ;)

Poster un commentaire:

Nom/Name
Comment.

#. (18 Jun 2015 - 05:32)

#. (10 Mar 2015 - 10:58)

zadd
#.Pharmc776 (13 Aug 2014 - 23:14)

Very nice site!
#.Pharmd529 (13 Aug 2014 - 23:13)

Very nice site! [url=http://aixypeo2.com/ayaota/2.html]cheap goods[/url]
#.Pharme378 (13 Aug 2014 - 23:13)

Very nice site! <a href="http://aixypeo2.com/ayaota/1.html">cheap goods</a>
#.Pharme271 (12 Aug 2014 - 17:02)

Very nice site!
#.Pharme733 (12 Aug 2014 - 17:02)

Very nice site! cheap goods http://apeoixy2.com/tqsrv/4.html
#.Pharmg95 (12 Aug 2014 - 17:02)

Very nice site! [url=http://apeoixy2.com/tqsrv/2.html]cheap goods[/url]
#.Pharmd373 (12 Aug 2014 - 17:01)

Very nice site! <a href="http://apeoixy2.com/tqsrv/1.html">cheap goods</a>
#.Pharmc891 (11 Aug 2014 - 10:37)

Very nice site!
#.Pharmd122 (11 Aug 2014 - 10:37)

Very nice site! cheap goods http://ypxoiea2.com/qyaotq/4.html
#.Pharmc261 (11 Aug 2014 - 10:37)

Very nice site! [url=http://ypxoiea2.com/qyaotq/2.html]cheap goods[/url]
#.Pharmd763 (11 Aug 2014 - 10:36)

Very nice site! <a href="http://ypxoiea2.com/qyaotq/1.html">cheap goods</a>
#.Pharmd278 (10 Aug 2014 - 04:41)

Very nice site!
#.Pharmf843 (10 Aug 2014 - 04:40)

Very nice site! cheap goods http://oixapey2.com/aqsrr/4.html
#.Pharmf525 (10 Aug 2014 - 04:39)

Very nice site! <a href="http://oixapey2.com/aqsrr/1.html">cheap goods</a>
#.Pharmd262 (09 Aug 2014 - 22:32)

Very nice site! cheap goods http://oixapey2.com/aqsrr/4.html
#.Pharmd481 (09 Aug 2014 - 22:20)

Very nice site! [url=http://oixapey2.com/aqsrr/2.html]cheap goods[/url]
#.Pharme706 (09 Aug 2014 - 22:18)

Very nice site! <a href="http://oixapey2.com/aqsrr/1.html">cheap goods</a>
#.Pharma248 (08 Aug 2014 - 15:48)

Very nice site!
 1  2  3
50 commentaires