181 votes

PHP $_SERVER['HTTP_HOST'] vs $_SERVER['SERVER_NAME'], suis-je la compréhension de l'homme pages correctement?

J'ai fait beaucoup de recherche et aussi de lire le PHP $_SERVER page de man. Puis-je avoir ce droit à l'égard de laquelle l'utiliser pour mes scripts PHP pour de simples définitions utilisées tout au long de mon site?

$_SERVER['SERVER_NAME'] est basé sur votre serveur web fichier de config (Apache2 dans mon cas), et qui varie selon quelques directives: (1) VirtualHost, (2) le nom du serveur (3) UseCanonicalName, etc.

$_SERVER['HTTP_HOST'] est basé sur la demande du client.

Par conséquent, il me semble que le propre de l'utiliser pour faire mes scripts aussi compatible que possible serait $_SERVER['HTTP_HOST']. Cette hypothèse est correcte?

Suivi des commentaires:

Je suppose que je suis un peu paranoïaque après la lecture de cet article, et notant que quelqu'un a dit "qu'ils ne serait pas confiance tout de la valeur de $_SERVER vars":

http://markjaquith.wordpress.com/2009/09/21/php-server-vars-not-safe-in-forms-or-links/

et aussi:

http://www.php.net/manual/en/reserved.variables.server.php (commentaire: Vladimir Kornea 14-Mar-2009 01:06)

Apparemment, la discussion porte principalement sur l' $_SERVER['PHP_SELF'] et pourquoi vous ne devriez pas l'utiliser dans l'attribut action du formulaire sans échapper pour empêcher les attaques XSS.

Ma conclusion au sujet de ma question initiale, c'est qu'il est "sûr" pour utiliser $_SERVER['HTTP_HOST'] pour tous les liens sur un site sans avoir à se soucier des attaques XSS, même lorsqu'il est utilisé dans les formulaires.

S'il vous plaît corrigez-moi si je me trompe.

166voto

Gumbo Points 279147

C'est probablement tout le monde est d'abord pensé. Mais c'est un peu plus difficile. Voir Chris Shiflett de l'article SERVER_NAME Contre HTTP_HOST.

Il semble qu'il n'y a pas de solution miracle. Seulement quand vous forcer Apache à utiliser le nom canonique vous obtiendrez toujours le bon nom de serveur avec SERVER_NAME.

Donc, soit vous allez ou vous vérifiez le nom de l'hôte contre une "liste blanche":

$allowed_hosts = array('foo.example.com', 'bar.example.com');
if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts)) {
    header($_SERVER['SERVER_PROTOCOL'].' 400 Bad Request');
    exit;
}

87voto

Simon Points 4467

Juste une remarque supplémentaire - si le serveur s'exécute sur un port autre que le port 80 (comme cela peut être commun à un développement et à l'intranet de la machine) alors HTTP_HOST contient le port, tandis que l' SERVER_NAME ne le sont pas.

$_SERVER['HTTP_HOST'] == 'localhost:8080'
$_SERVER['SERVER_NAME'] == 'localhost'

(Au moins, c'est ce que j'ai remarqué dans Apache basé sur le port des hôtes virtuels)

Comme Mike l'a noté ci-dessous, HTTP_HOST ne pas contenir :443 lors de l'exécution sur HTTPS (sauf si vous êtes en cours d'exécution sur un port non standard, que je n'ai pas testé).

32voto

bobince Points 270740

Utilisez soit. Ils sont à la fois aussi (in)secure, comme dans de nombreux cas, SERVER_NAME est simplement peuplé de HTTP_HOST de toute façon. J'ai l'habitude d'aller pour HTTP_HOST, de sorte que l'utilisateur reste sur le nom de l'hôte qu'ils ont commencé. Par exemple, si j'ai le même site sur un .com et .org domaine, je ne veux pas l'envoyer à quelqu'un .org pour .com, particulièrement si elles ont des jetons de connexion .org, qu'ils venaient de perdre si elles sont envoyées à l'autre domaine.

De toute façon, vous avez juste besoin d'être sûr que votre webapp ne jamais répondre pour les bonnes domaines. Cela peut être fait soit (un) avec une demande de vérification côté comme Gumbo, ou (b) en utilisant un hôte virtuel sur le nom de domaine(s) que vous voulez qui ne répond pas aux demandes qui donnent un inconnu en-tête d'Hôte.

La raison pour cela est que si vous permettre à votre site d'être accessible dans tout l'ancien nom, vous vous exposez à DNS rebinding attaques (où un autre site du nom d'hôte points de votre adresse IP, un utilisateur accède à votre site avec l'attaquant du nom d'hôte, le nom est déplacée vers l'IP de l'attaquant, prendre vos cookies/auth) et de moteur de recherche, de détournement (où un attaquant points de leur propre nom d'hôte de votre site et essaie de faire les moteurs de recherche voient comme le "meilleur" des primaires nom d'hôte).

Apparemment, la discussion porte principalement sur $_SERVER['PHP_SELF'] et pourquoi vous ne devriez pas l'utiliser dans l'attribut action du formulaire sans échapper pour empêcher les attaques XSS.

Pfft. Eh bien, vous ne devriez pas utiliser quelque chose de tout attribut, sans s'échapper avec htmlspecialchars($string, ENT_QUOTES), donc il n'y a rien de spécial sur les variables de serveur.

26voto

antitoxic Points 1804

C'est une verbose la traduction de ce que Symfony utilise pour obtenir le nom d'hôte (voir le deuxième exemple pour une traduction plus littérale):

function getHost() {
    $possibleHostSources = array('HTTP_X_FORWARDED_HOST', 'HTTP_HOST', 'SERVER_NAME', 'SERVER_ADDR');
    $sourceTransformations = array(
        "HTTP_X_FORWARDED_HOST" => function($value) {
            $elements = explode(',', $value);
            return trim(end($elements));
        }
    );
    $host = '';
    foreach ($possibleHostSources as $source)
    {
        if (!empty($host)) break;
        if (empty($_SERVER[$source])) continue;
        $host = $_SERVER[$source];
        if (array_key_exists($source, $sourceTransformations))
        {
            $host = $sourceTransformations[$source]($host);
        } 
    }

    // Remove port number from host
    $host = preg_replace('/:\d+$/', '', $host);

    return trim($host);
}

Obsolète:

C'est ma traduction pour mettre à nu le PHP d'une méthode utilisée dans le framework Symfony qui tente d'obtenir le nom d'hôte à partir de toutes les manières possibles afin de les meilleures pratiques:

function get_host() {
    if ($host = $_SERVER['HTTP_X_FORWARDED_HOST'])
    {
        $elements = explode(',', $host);

        $host = trim(end($elements));
    }
    else
    {
        if (!$host = $_SERVER['HTTP_HOST'])
        {
            if (!$host = $_SERVER['SERVER_NAME'])
            {
                $host = !empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '';
            }
        }
    }

    // Remove port number from host
    $host = preg_replace('/:\d+$/', '', $host);

    return trim($host);
}

8voto

Powerlord Points 43989

La différence majeure entre les deux est que l' $_SERVER['SERVER_NAME'] est un serveur variable contrôlée, tout en $_SERVER['HTTP_HOST'] est contrôlée par l'utilisateur de la valeur.

La règle de base est de ne pas faire confiance à des valeurs de l'utilisateur, $_SERVER['SERVER_NAME'] est le meilleur choix.

Que le Gombo a souligné, Apache va construire SERVER_NAME de l'utilisateur des valeurs fournies si vous ne définissez pas d' UseCanonicalName On.

Edit: cela dit, si le site est à l'aide d'un nom d'hôte virtuel basé sur le HTTP en-tête d'Hôte est la seule façon de parvenir à des sites qui ne sont pas le site par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X