-
[Sécurité PHP] Toujours vérifier le Referer lors d'un envoi par POST
Par Skreo dans Web development le 26 Décembre 2008 à 14:27![[Sécurité PHP] Toujours vérifier le Referer lors d'un envoi par POST](http://data0.eklablog.com/skreo/mod_article313986_1.jpg)
C'est un aspect très souvent négligé de la sécurité des sites web, et qui est pourtant critique.
Par exemple, si Facebook n'avait pas prévu ce genre de sécurité, nous pourrions partir du postulat qu'il y a une chance non négligeable qu'un visiteur soit connecté à Facebook (par session ou cookies). Prenons alors une page web visitée par quelques dizaines ou centaines de visiteurs par jour, un blog par exemple. Sur cette page, nous allons mettre un formulaire identique à celui permettant de modifier le profil sur Facebook. Une ligne de javascript suffira à envoyer le formulaire ( $("id_form").submit() ), avec tout plein de grossièretés qui viendront égayer le profil de l'utilisateur

C'est de cette manière qu'Olivier Duffez s'est fait pirater son compte Gmail puis le nom de domaine Webrankinfo.com ! En effet, le pirate s'est débrouillé pour que M. Duffez se retrouve sur une page envoyant un formulaire vers la page de création de filtre de Gmail. Et comme une session Gmail était ouverte sur l'ordinateur de M. Duffez, le formulaire en question a pu créer un filtre qui transférait tous les e-mails reçus au spammeur. Le spammeur a ensuite utilisé le formulaire "Mot de passe oublié" du registrar chez lequel est enregistré webrankinfo.com, et a donc reçu l'e-mail permettant de modifier le mot de passe.
Alors ? N'est-ce pas critique comme faille ?
Ce type d'attaque est appelé Cross-Site Request Forgery, et n'est pas très connu en raison d'un manque de communication à ce propos.
Voyons comment l'étudier concrètement, et comment éviter ce genre de déboires.Pour vous montrer un exemple concret, créons une page affichant les données reçues par POST :
http://data0.eklablog.com/skreo/perso/test_referer.phpCode de la page :
Ensuite, sur un nom de domaine différent (ici skreo.net), créons un petit formulaire qui envoie des données à cette page :
<form action="http://data0.eklablog.com/skreo/perso/test_referer.php" method="post" id="form_test_referer">
Variable "var" : <input type="text" value="" name="var" /><br />
<input type="submit" value="Envoyer" />
</form>Ce qui donne ceci :
Vous pouvez tester ce formulaire, vous voyez bien qu'on peut envoyer n'importe quelles données par POST vers un autre domaine. Un petit bout de code Javascript à la suite du formulaire permet d'envoyer le formulaire immédiatement sans même demander l'avis du visiteur :
Voyons maintenant comment empêcher dans la majorité des cas ce genre de hacks, avec l'aide du Referer. Je dis bien "dans la majorité des cas", car parfois le visiteur règle son navigateur internet pour que le referer soit vide.
Nous allons donc comparer le Referer avec le nom de domaine de la page courante, et vider la variable $_POST s'il est différent. Reprenons notre fichier test_referer.php et nommons le test_referer2.php :
<?php
// Vérification du Referer pour les variables passées en POST
if(isset($_SERVER['HTTP_REFERER'])
&& $_SERVER['HTTP_REFERER']!=''
&& substr($_SERVER['HTTP_REFERER'], 7, strlen($_SERVER['SERVER_NAME'])) != $_SERVER['SERVER_NAME']){
$_POST = array();
}
?>
<pre>
Données reçues par POST :
$_POST = <?php
print_r($_POST);
?>
</pre>Reprenons notre formulaire pour tester, mais cette fois vers test_referer2.php :
Et le tour est joué !
La page accepte toujours les envois de données par POST provenant du même nom de domaine, mais n'accepte pas les autres !Si vous avez un site web, je vous conseille très fortement de mettre en place cette sécurité, si ce n'est pas déjà le cas

Partager cet article :
Tags : php, securite, referer
Suivre le flux RSS des commentaires de cet article
Revenir à la liste des articles
-
Commentaires
1Darklg / Kev26 Décembre 2008 à 15:56Ca ne risque pas de déconner, vu que c'est le navigateur qui choisit d'envoyer ou non un Referrer ?Nop, lorsqu'il n'est pas configuré spécifiquement, le navigateur envoie presque toujours le referer. Et si tu regardes le script, si aucun referer n'est renseigné, on laisse la variable $_POST tranquille ^^ Donc pour une grande majorité des visiteurs, cette sécurité est efficace.
Par contre ça n'est pas efficace pour les gens qui modifient eux-même le referer, mais ces gens-là sont sensés en connaitre les risques...Tu parle d'une faille de sécurité, ok. Mais si je suis un hackers et que je change le referer que j'envoi (envoi d'une requete http simple), ta faille reste toujours active non ? Ca ne corrige pas vraiment la faille, ça la diminue juste un peu je trouve.@Defaite : Non, pas du tout, ce que tu n'as pas l'air d'avoir compris, c'est que cette faille utilise les sessions actives du navigateur du visiteurs pour envoyer des formulaires. Là tu me parles de changer le referer de la requête. D'accord, c'est tout à fait possible, avec un petit script en php par exemple, mais alors tu n'as pas les données de session de l'utilisateur, et donc la faille n'est pas exploitable.
Le truc, c'est que tu ne peux pas modifier le referer des requêtes que font les visiteurs. Seuls eux peuvent le faire, en configurant leur navigateur.Le problème avec le referer c'est que c'est une donnée qui dépends du navigateur du visiteur. Ok par défaut il n'y a pas de problème, mais se baser uniquement dessus peut avoir de contreparties bloquantes (pour ma part je bloque souvent le réferer, si je ne peux plus accéder à) des services à cause de ca...).
Les tokens sont quand à eux, passent partout, et ne sont pas si durs à mettre en place, et deviennent standards dans les frameworks comme symfonyOui tu as tout à fait raison, je présente la solution du referer comme solution de base, mais elle n'est évidemment pas sûre à 100%.
Les tokens sont très lourds à mettre en place à grande échelle : par exemple il ne faudrait pas le faire systématiquement sur EklaBlog, car presque chaque ouverture d'une fenêtre de modification fait appel à POST (par Ajax).
Mais les tokens sont à utiliser pour les formulaires sensibles.Oui, j'avoue c'est assez dur à mettre un site à jour dans son intégralité, si on y a pas pensé dès le début... Modifier chaque formulaire, c'est galère (mais pas plus que la méthode que tu donnes je pense) !
Ps : autre méthode: la captcha... bon ok je sorsLe problème n'est pas tellement de mettre à jour un système déjà existant. Je parle surtout de performances. Parce que générer 1 token par seconde, 300 000 dans la journée, c'est pas très bon pour la base de donnée et les performances du serveur.
Pour le Referer, il suffit au contraire de placer les 3 lignes de codes que je donne dans le fichier de configuration du site, et elles s'appliqueront sans problème à l'intégralité des pages.Hey ça marche pas mal ton petit truc,
Je me suis pris les alertes JS dans la tronche puis impossible de poster mon petit comment...
http://www.deliciouscadaver.com/outil-de-spam-referer-genti.html
:)11yesnet14 Janvier 2009 à 21:58mouai mouai... merci pour cet article, au moins çà permet d'en discuter. Car je ne suis pas pour le referer :
- le referer est majoritairement utilisé pour tracer les visteurs (stats)
- si l'internaute novice utilise un navigateur mal configuré, il ne pourra pas envoyer ledit formulaire. Et avant de savoir re-activer le referer, woualou
- enfin et surtout, il devient impossible de bookmarker la page...
Oui la sécurité est essentielle, mais d'autres moyens existent.@yesnet: Bookmarker la page ? En quoi cela devient-il impossible ?
Pour le navigateur novice, c'est vrai que ça peut arriver, mais c'est extrêmement rare. Pour preuve, j'ai effectué un log sur les 15 derniers jours de toutes les requêtes bloquées par cette technique sur EklaBlog (10 à 15 000 VU/jour), et ça donne :
- 27 spams bloqués :
- 2 utilisateurs initiés bloqué (512banque qui a commenté plus haut, et un membre d'EklaBlog que je connais)
- divarvel qui a eu un referer qui a merdé apparemment à cause de Iceweasel. Il faudra que je gère ce cas.
- 4 requêtes faites sous IE7 qui apparemment a aussi mal géré le referer.13yesnet15 Janvier 2009 à 13:39Tu as raison on peut bookmarker la page.
D'une façon générale, je suis contre exiger des réglages côté machine client. Il vaut mieux utiliser les fonctions côté serveur,c'est plus fiable car une seule source et les visiteurs restent libre de leur navigateur. C'est au serveur d'être l'unique référant, on ne doit rien imposer à la machine client.
Si un super navigateur ultra protégé contre les données personnelles voit le jour, ou un navigateur minimaliste n'incluant par le referer, le formulaire ne marche plus.Hmmm vas dire ça aux concepteurs de Facebook (entre autre) qui utilisent ce type d'astuce. Au moins ça a le mérite de bien marcher dans une très grande majorité des cas, et à moindre frais.
Si tu as une sécurité côté serveur à proposer, je t'écoute
Même avec un token, il suffit que le pirate récupère la clé token juste avant de rediriger le visiteur vers la page avec le token en argument...15yesnet15 Janvier 2009 à 17:22Effectivement, tu m'as convaincu ;)Super, bravo ça marche nickel ton petit truc
Tout comme 512banque (salut à toi
) et bien je me suis pris
les alertes JS dans la tronche donc désactiver le truc pour poster mon petit commentaire.
19dimebagplan25 Mai 2010 à 03:51Bonjour, un grand merci pour cette article tres interessant.
Je trouve en effet qu'on ne parle pas asser de ce genre de protection qui semble vraiment essentiel !
Une question :
[quote]
Pour le Referer, il suffit au contraire de placer les 3 lignes de codes que je donne dans le fichier de configuration du site, et elles s'appliqueront sans problème à l'intégralité des pages.
[/quote]
Ca m'interesse, qu'entends tu par fichier de configuration du site ?
tu crée une page php avec ce code (et d'autres types de protections je suppose) et ensuite tu fais un include au debut de chacunes de tes pages php ?
Merci, a tres bientot et bonne continuation.
Ajouter un commentaire
