web-dev-qa-db-fra.com

$ _SERVER [] est-il une source sûre de données en PHP?

Puis-je compter à 100% sur $_SERVER[] pour être une source sûre de données que je n'ai pas besoin de désinfecter comme je le fais $_GET[] et $_POST[]?

29
user2079272

Ceci est tiré d'une de mes questions sur le débordement de pile: Quelles variables $ _SERVER sont sûres?

Contrôlé par le serveur

Ces variables sont définies par l'environnement du serveur et dépendent entièrement de la configuration du serveur.

  • 'GATEWAY_INTERFACE'
  • 'SERVER_ADDR'
  • 'SERVER_SOFTWARE'
  • 'DOCUMENT_ROOT'
  • 'SERVER_ADMIN'
  • 'SERVER_SIGNATURE'

Partiellement contrôlé par le serveur

Ces variables dépendent de la demande spécifique envoyée par le client, mais ne peuvent prendre qu'un nombre limité de valeurs valides, car toutes les valeurs non valides doivent être rejetées par le serveur Web et ne pas provoquer l'appel du script au départ. Ils peuvent donc être considérés fiables .

  • 'HTTPS'
  • 'REQUEST_TIME'
  • 'REMOTE_ADDR' *
  • 'REMOTE_Host' *
  • 'REMOTE_PORT' *
  • 'SERVER_PROTOCOL'
  • 'HTTP_Host'
  • 'SERVER_NAME'
  • 'SCRIPT_FILENAME'
  • 'SERVER_PORT'
  • 'SCRIPT_NAME'

* Le REMOTE_ les valeurs sont garanties comme étant l'adresse valide du client, telle que vérifiée par une négociation TCP/IP. Il s'agit de l'adresse à laquelle toute réponse sera envoyée. REMOTE_Host repose cependant sur des recherches DNS inversées et peut donc être usurpé par des attaques DNS contre votre serveur (dans ce cas, vous avez quand même de plus gros problèmes). Cette valeur peut être un proxy, ce qui est une simple réalité du protocole TCP/IP et rien pour lequel vous ne pouvez rien faire.

† Si votre serveur Web répond à toute demande indépendamment de l'en-tête Host, cela doit également être considéré comme dangereux. Voir Quelle est la sécurité de $ _SERVER [“HTTP_Host”]? .
Voir aussi http://shiflett.org/blog/2006/mar/server-name-versus-http-Host .

Valeurs entièrement arbitraires contrôlées par l'utilisateur

Ces valeurs ne sont pas vérifiées du tout et ne dépendent d'aucune configuration de serveur, ce sont des informations entièrement arbitraires envoyées par le client.

  • 'argv', 'argc' (applicable uniquement à l'invocation CLI, ce qui ne concerne généralement pas les serveurs Web)
  • 'REQUEST_METHOD'
  • 'QUERY_STRING'
  • 'HTTP_ACCEPT'
  • 'HTTP_ACCEPT_CHARSET'
  • 'HTTP_ACCEPT_ENCODING'
  • 'HTTP_ACCEPT_LANGUAGE'
  • 'HTTP_CONNECTION'
  • 'HTTP_REFERER'
  • 'HTTP_USER_AGENT'
  • 'AUTH_TYPE' §
  • 'PHP_AUTH_DIGEST' §
  • 'PHP_AUTH_USER' §
  • 'PHP_AUTH_PW' §
  • 'PATH_INFO'
  • 'ORIG_PATH_INFO'
  • 'REQUEST_URI' (peut contenir des données entachées)
  • 'PHP_SELF' (peut contenir des données corrompues, par exemple /index.php/evilstring)
  • 'PATH_TRANSLATED'
  • tout autre 'HTTP_' valeur

‡ Peut être considéré fiable tant que le serveur Web n'autorise que certaines méthodes de demande.

§ Peut être considéré fiable si l'authentification est entièrement gérée par le serveur Web.

Le superglobal $_SERVER inclut également plusieurs variables d'environnement. Que ceux-ci soient "sûrs" ou non dépend de la façon dont (et où) ils sont définis. Ils peuvent aller de complètement contrôlés par le serveur à entièrement contrôlés par l'utilisateur.

44
rook

Puis-je compter à 100% sur $ _SERVER [] pour être une source sûre de données que je n'ai pas besoin de nettoyer comme je le fais pour $ _GET [] et $ _POST []?

Votre question indique immédiatement un échec. Toutes les sources d'entrée doivent être nettoyées. L'entrée n'est pas seulement considérée comme des canaux que l'utilisateur peut contrôler directement, mais comme toutes les sources de données en dehors de votre application.

Pensez-y de cette façon, votre application a 2 façons d'obtenir des données: les informations codées en dur dans votre application et les saisir. Même s'il est généré par un autre programme sur le même système, il est toujours entré dans votre programme.

L'idiome commun Filter-In, Escape-Out s'applique non seulement à l'entrée utilisateur, mais à tout ce qui entre et sort de votre application.

Donc, si c'est dans $_SERVER, il [[# # ~] doit [~ # ~] être filtré/aseptisé. Vous ne devez jamais vous fier à quelque chose qui n'est pas codé en dur dans votre application.

Pourquoi est-ce important? Imaginons que vous filtriez toutes les entrées de l'utilisateur, mais que vous approuviez ensuite les données provenant de votre base de données. Si je peux exploiter un trou dans votre filtrage, je peux injecter des données qui deviennent alors fiables. Cela peut entraîner XSS ou SQLi de second ordre. Mais si vous filtrez tout ce qui entre dans votre application, quand elle arrive, peu importe d'où elle vient, alors vous serez en sécurité!

Donc non, vous ne pouvez jamais compter à 100% sur quoi que ce soit dans $_SERVER, $_GET, $_POST, $_COOKIE, $_REQUEST, $_ENV, $argc, $argv, depuis votre base de données, depuis le système de fichiers (à part votre code contrôlé par version), etc ...

14
ircmaxell

Pas une question idiote du tout!

Beaucoup (mais pas toutes) des variables $ SERVER sont transmises depuis le navigateur des utilisateurs (ou peuvent être influencées par l'utilisateur), par exemple les QUERY_STRING, REQUEST_URI et toutes les variables HTTP_ *.

Même la variable REMOTE_ADDR peut être usurpée à l'aide de sockets bruts (mais uniquement avec des adresses IP valides à ma connaissance).

Je leur échapperais tous comme une bonne politique.

http://php.net/manual/en/reserved.variables.server.php

6
GBC

Il n'existe pas de "source sûre de données". Vous devez toujours vous assurer que les données sont au bon format lorsque vous les transmettez à autre chose.

Si vous effectuez une sortie vers SQL à l'intérieur d'une chaîne délimitée par une apostrophe (') [1], vous devez échapper les apostrophes (ou tout autre élément susceptible de casser la chaîne). Si vous effectuez une sortie vers une chaîne délimitée par une apostrophe Javascript [2], vous devez échapper à la fois le code HTML et les apostrophes. Tout dépend de ce que vous sortez. Une chaîne parfaitement sûre peut casser le script cible, même si ce n'est pas de manière malveillante. (Souvent cependant, s'il peut être brisé, il peut également être exploité.)

[1] Exemple: $db->query("SELECT * FROM users WHERE name = '$username'");
[2] Exemple: <script>alert('Hi <?php echo $username;?>');</script>

J'ai parlé de cette fuite sur mon blog, bien que mon article soit spécifiquement sur XSS, je pense que le même principe s'applique ici aussi: Qu'est-ce que XSS et comment protéger votre site Web .

À moins que vous ne sachiez que PHP lui-même applique déjà un format spécifique, et vous ne pouvez presque jamais en être sûr, vous pouvez considérer tout comme dangereux. Les adresses IP viennent généralement au format xxxx, mais elles peuvent également être x: x: x: x: x: x: x: x pour IPv6. Ou même 0: 0: 0: 0: 0: ffff: xxxx pour les destinations IPv4 dans les paquets IPv6. Si vous ne le savez pas, cela peut conduire à des bugs très intéressants.

Maintenant, une adresse IP ne contiendra jamais d'apostrophe, non ..? Eh bien, il y a ces gens qui recherchent l'en-tête $ _SERVER ["HTTP_X_FORWARDED_FOR"] avant d'utiliser l'adresse distante. C'est génial, tant que l'en-tête est correctement défini (comme l'a également souligné @Ladadadada dans un commentaire à la réponse de @ GBC), mais cela peut également être une parodie. Ensuite, lorsque vous utilisez les données que d'autres ont stockées dans la base de données, vous risquez de récupérer des éléments malveillants ... Donc, en fin de compte, ne faites jamais confiance aux entrées. Mieux vaut le sécuriser trop que l'oublier une fois.

3
Luc