Page 1 sur 1

X-Forwarded-For sur Varnish et PHP

Publié : 26 févr. 2016 10:15
par Malekal_morte
Un petit mot sur le X-Forwarded-For sur Varnish et PHP de manière générale.

Pour rappel, le X-Forwarded-For est normalement utilisé par un proxy pour insérer l'IP client à l'origine de la requête, l'IP client devenant celle du proxy. Cela permet de conserver l'IP client comme information. Étant donné qu'elle est contenue dans l'entête, le client a la possibilité de la falsifier et donc d'obtenir un X-Forwarded-For erroné.

Par défaut, Varnish va insérer dans le X-Forwarded-For le contenu du X-Forwarded-For de la requête HTTP initiale et y ajouter l'IP client. Si vous manipulez ces derniers, par exemple en PHP, il faudra mettre quelques filtres ou modifier les règles Varnish.

Pour illustrer ceci, quelques exemples avec la configuration Varnish 4.0 par défaut et sans filtre sur PHP.

Une page de test toute bête :

Code : Tout sélectionner

<?php
echo "IP ".$_SERVER["REMOTE_ADDR"]."<br />";
echo "IP FORWARD ".$_SERVER['HTTP_X_FORWARDED_FOR']."<br />";
echo "Client IP :".$_SERVER['HTTP_CLIENT_IP'];
?>
Varnish récupère ce qu'on lui envoie dans le header :
Image

Image

Sur Firefox, l'extension Modify Headers permet de manipuler les headers HTTP.

La page PHP affichant le HTTP_X_FORWARDED_FOR en brute, on peut y injecter du code.

Image

Image

Par exemple, les sites suivants ne font aucune vérification..

Image

Image

Image

Ce n'est pas spécialement grave mais ça peut le devenir. Prenons l'exemple d'un forum où l'IP est affichée. Il est alors possible d'injecter du code pour par exemple récupérer le cookie d'authentification et/ou tenter d'obtenir des accès avec des privilèges.

Varnish permet de mettre des filtres regex pour ne garder que des IPs valides, mais gardez à l'esprit qu'une personne pourra y insérer n'importe quelle valeur dans les headers. Varnish ajoutera tout de même à la fin, la vraie IP mais il n'empêche.

Exemple :
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For,", ([0-9]{1,3}\.){3}([0-9]{1,3})$","");
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*),([^,]+)$", "\1");
ou :
set req.http.X-Forwarded-For = client.ip;
Faire attention côté PHP. Plus globalement, faire attention aux valeurs pouvaient être manipulées.