Est-il "sûr" d'utiliser $_SERVER['HTTP_HOST']
pour tous les liens sur un site sans avoir à se soucier des attaques XSS, même lorsqu'ils sont utilisés dans des formulaires?
Oui, c'est sûr à utiliser $_SERVER['HTTP_HOST']
, (et même $_GET
et $_POST
) tant que vous les vérifiez avant de les accepter. Voici ce que je fais pour les serveurs de production sécurisés:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
$reject_request = true;
if(array_key_exists('HTTP_HOST', $_SERVER)){
$host_name = $_SERVER['HTTP_HOST'];
// [ need to cater for `host:port` since some "buggy" SAPI(s) have been known to return the port too, see http://goo.gl/bFrbCO
$strpos = strpos($host_name, ':');
if($strpos !== false){
$host_name = substr($host_name, $strpos);
}
// ]
// [ for dynamic verification, replace this chunk with db/file/curl queries
$reject_request = !array_key_exists($host_name, array(
'a.com' => null,
'a.a.com' => null,
'b.com' => null,
'b.b.com' => null
));
// ]
}
if($reject_request){
// log errors
// display errors (optional)
exit;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
echo 'Hello World!';
// ...
L'avantage de $_SERVER['HTTP_HOST']
est que son comportement est plus bien défini que $_SERVER['SERVER_NAME']
. Contraste ➫➫ :
Contenu de l'hôte: en-tête de la requête en cours, s'il y en a un.
avec:
Le nom de l'hôte du serveur sous lequel le script actuel s'exécute.
L'utilisation d'une interface mieux définie comme cela $_SERVER['HTTP_HOST']
signifie que plus de SAPI l'implémenteront en utilisant un comportement fiable et bien défini. (Contrairement à l'autre .) Cependant, il est encore totalement dépendant de SAPI ➫➫ :
Il n'y a aucune garantie que chaque serveur Web fournira l'un de ces [$_SERVER
entrées]; les serveurs peuvent en omettre certains ou en fournir d’autres non répertoriés ici.
Pour comprendre comment récupérer correctement le nom d'hôte, vous devez d'abord et avant tout comprendre qu'un serveur qui ne contient que du code n'a aucun moyen de connaître (condition préalable à la vérification) son propre nom sur le réseau. Il doit s'interfacer avec un composant qui lui fournit son propre nom. Cela peut être fait via:
Habituellement, cela se fait via le fichier de configuration local (SAPI). Notez que vous l'avez configuré correctement, par exemple dans Apache ➫➫ :
Un certain nombre de choses doivent être «truquées» pour que l'hôte virtuel dynamique ressemble à un hôte normal.
Le plus important est le nom du serveur qui est utilisé par Apache pour générer des URL auto-référentielles, etc. Il est configuré avec la ServerName
directive, et il est disponible pour les CGI via la SERVER_NAME
variable d'environnement.
La valeur réelle utilisée au moment de l'exécution est contrôlée par le paramètre UseCanonicalName.
Avec UseCanonicalName Off
le nom du serveur provient du contenu de l'en- Host:
tête de la demande. Avec UseCanonicalName DNS
elle vient d'une recherche inversée DNS de l'adresse IP de l'hôte virtuel. Le premier paramètre est utilisé pour l'hébergement virtuel dynamique basé sur le nom, et le dernier est utilisé pour l'hébergement ** basé sur IP.
Si Apache ne peut pas travailler sur le nom du serveur parce qu'il n'y a pas d'en- Host:
tête ou le DNS recherche échoue alors la valeur configurée avec ServerName
est utilisé à la place.