118 votes

Qu'y a-t-il de mal à utiliser $_REQUEST[] ?

J'ai vu un certain nombre de messages ici disant qu'il ne faut pas utiliser la fonction $_REQUEST variable. Je ne le fais pas d'habitude, mais parfois c'est pratique. Qu'est-ce qu'il y a de mal à ça ?

2 votes

Voir les questions et réponses connexes : stackoverflow.com/questions/1149118/

2 votes

Depuis php 5.3, le php.ini par défaut indique que seules les données GET et POST sont placées dans le fichier $_REQUEST . Ver php.net/request_order Je viens de tomber sur cette rupture de rétrocompatibilité en m'attendant à ce que les données des cookies soient dans le fichier $_REQUEST et je me demandais pourquoi ça ne marchait pas ! Donc la plus grande raison d'éviter d'utiliser $_REQUEST est maintenant que votre script ne peut pas définir request_order lui-même (il est PHP_INI_PERDIR ), donc un changement de php.ini peut facilement casser les hypothèses sur lesquelles votre script est construit. Mieux vaut mettre ces hypothèses directement dans votre script.

187voto

bobince Points 270740

Il n'y a absolument rien de mal à prendre l'avis des deux parties. $_GET y $_POST de manière combinée. En fait, c'est ce que vous voulez presque toujours faire :

  • pour une simple requête idempotente habituellement soumise via GET, il est possible que la quantité de données que vous voulez ne tienne pas dans une URL et qu'elle doive être mutée en une requête POST à la place pour des raisons pratiques.

  • pour une requête qui a un effet réel, il faut vérifier qu'elle est soumise par la méthode POST. Mais la façon de le faire est de vérifier $_SERVER['REQUEST_METHOD'] explicitement, ne pas se fier à $_POST étant vide pour un GET. Et de toute façon si la méthode est POST mais il est toujours possible de supprimer certains paramètres d'interrogation de l'URL.

Non, le problème avec $_REQUEST n'a rien à voir avec la confusion des paramètres GET et POST. C'est qu'il inclut également, par défaut, les paramètres suivants $_COOKIE . Et les cookies ne sont pas du tout comme les paramètres de soumission de formulaire : il ne faut presque jamais les traiter de la même manière.

Si, par mégarde, un cookie portant le même nom que l'un des paramètres de votre formulaire est installé sur votre site, les formulaires qui dépendent de ce paramètre cesseront mystérieusement de fonctionner correctement, car les valeurs du cookie remplaceront les paramètres attendus. Cela est très facile à faire si vous avez plusieurs applications sur le même site, et peut être très difficile à déboguer lorsque vous n'avez qu'un couple d'utilisateurs avec de vieux cookies que vous n'utilisez plus qui traînent et cassent les formulaires d'une manière que personne d'autre ne peut reproduire.

Vous pouvez remplacer ce comportement par le comportement beaucoup plus raisonnable suivant GP (non C ) avec l'ordre demande_ordre en PHP 5.3. Lorsque cela n'est pas possible, j'éviterai personnellement $_REQUEST et, si j'avais besoin d'un tableau combiné GET+POST, le créer manuellement.

2 votes

Ces situations (données trop longues pour être soumises via GET) sont une exception et non une règle.

1 votes

Belle réponse. J'ai aussi remarqué qu'avec des frameworks comme Zend Framework, les paramètres GET et POST sont combinés en un seul objet de requête. Cela ne m'avait jamais frappé jusqu'à ce que je lise votre article.

0 votes

Par défaut, le demande_ordre est réglé sur "GP" dans php.ini à partir de PHP 5.4+, donc je dirais que vous pouvez le faire... mais comme toujours, soyez prudent.

79voto

Gordon Points 156415

J'ai parcouru quelques messages de groupes de discussion sur Internes PHP et a trouvé une discussion intéressante sur le sujet. Le fil de discussion initial portait sur autre chose, mais une remarque de Stefan Esser, un (si ce n'est pas un le site ), expert en sécurité dans le monde PHP, a orienté la discussion vers les implications en matière de sécurité de l'utilisation de $_REQUEST pour quelques messages.

Citant Stefan Esser sur les internes de PHP

$_REQUEST est l'une des plus grandes faiblesses de conception de PHP. Toute application utilisant $_REQUEST est probablement vulnérable aux problèmes de contrefaçon de requêtes Forgery. (Cela signifie que si, par exemple, un cookie nommé (age) existe, il remplacera toujours le contenu GET/POST et par conséquent des requêtes non désirées seront effectuées)

et dans un réponse ultérieure au même fil de discussion

Il ne s'agit pas du fait que quelqu'un puisse falsifier les variables GET, POST et COOKIE. Il s'agit du fait que les COOKIE vont écraser les données GET et POST dans les variables REQUEST.

Je pourrais donc infecter votre navigateur avec un cookie qui dit par exemple action=logout et à partir de ce jour vous ne pouvez plus utiliser l'application l'application parce que REQUEST[action] sera toujours logout (jusqu'à ce que vous supprimez manuellement le cookie).

Et pour vous infecter avec un COOKIE, c'est si simple...
a) Je pourrais utiliser une vulnérabilité XSS dans n'importe quelle application sur un sous-domaine.
b) Avez-vous déjà essayé d'installer un cookie pour *.co.uk ou *.co.kr lorsque vous possédez une domaine unique ?
c) Autres domaines croisés de quelque manière que ce soit...

Et si vous pensez que ce n'est pas un problème, alors je peux vous dire que il y a une possibilité simple de définir par exemple un cookie *.co.kr qui résulte plusieurs versions de PHP ne renvoient que des pages blanches. Imaginez : Un seul cookie pour tuer toutes les pages PHP dans *.co.kr.

Et en plaçant un ID de session illégal dans un cookie valide pour *.co.kr dans une variable appelée +PHPSESSID= illégal vous pouvez toujours DOS chaque PHP en Corée en utilisant des sessions PHP...

La discussion se poursuit pendant quelques posts supplémentaires et est intéressante à lire.


Comme vous pouvez le constater, le principal problème de $_REQUEST n'est pas tant qu'il contient des données provenant de $_GET et $_POST, mais aussi de $_COOKIE. D'autres personnes sur la liste ont suggéré de changer l'ordre dans lequel $_REQUEST est rempli, par exemple en le remplissant d'abord avec $_COOKIE, mais cela pourrait conduire à de nombreux autres problèmes potentiels, par exemple avec la gestion de la session .

Vous pouvez cependant omettre complètement $_COOKIES du global $_REQUEST, de manière à ce qu'il ne soit pas écrasé par les autres tableaux (en fait, vous pouvez le limiter à n'importe quelle combinaison de son contenu standard, comme l'option Manuel PHP sur le ordre_variable paramètre ini nous dit :

variable_order Définit l'ordre d'analyse des variables EGPCS (Environment, Get, Post, Cookie, and Server). Par exemple, si variables_order est défini à "SP", PHP créera les superglobales $_SERVER et $_POST, mais ne créera pas $_ENV, $_GET, et $_COOKIE. La valeur "" signifie qu'aucun superglobal ne sera créé.

Mais encore une fois, vous pouvez aussi envisager de ne pas utiliser $_REQUEST, tout simplement parce qu'en PHP, vous pouvez accéder à Environment, Get, Post, Cookie et Server dans leurs propres globales et avoir un vecteur d'attaque en moins. Vous devez toujours assainir ces données, mais c'est un souci de moins.


Maintenant, vous pouvez vous demander pourquoi $_REQUEST existe après tout et pourquoi il n'est pas supprimé. Cette question a également été posée sur PHP Internals. Citant Rasmus Lerdorf à propos de Pourquoi $_REQUEST existe-t-il ? sur les internes de PHP

Plus on supprime ce genre de choses, plus il devient difficile pour les gens de de passer rapidement à des versions plus récentes, plus rapides et plus sécurisées de PHP. C'est Cela cause bien plus de frustration pour tout le monde que quelques "vilaines" fonctionnalités héritées fonctionnalités. S'il y a une raison technique décente, de performance ou de sécurité, alors nous ne pouvons pas supprimer ces fonctionnalités. sécurité, alors nous devons y jeter un coup d'oeil. Dans ce cas, la Dans ce cas, la chose que nous devrions regarder n'est pas si nous devrions supprimer $_REQUEST mais si nous devons supprimer les données des cookies. De nombreuses configurations font déjà cela, y compris toutes les miennes, et il y a une forte raison de sécurité valide de sécurité pour ne pas inclure les cookies dans $_REQUEST. La plupart des gens utilisent $_REQUEST pour signifier GET ou POST, sans se rendre compte qu'il peut aussi contenir des cookies. des cookies et qu'en tant que tels, les méchants peuvent potentiellement faire des injections de cookies et casser des applications naïves.

En tout cas, j'espère que ça vous a éclairé.

2 votes

Je pense que cette discussion a été un peu trop généralisée. Le problème réel est la méconnaissance des développeurs, et non l'existence de cookies dans $_REQUEST en soi. Le PHPSESSID fixe, par exemple, sera de toute façon réinitialisé par un cookie par domaine avec le code de gestion de session actuel. Et pour certaines applications, un cookie remplaçant les variables de requête pourrait être vraiment souhaitable (par exemple, sort_order=ASC remplace une variable GET du formulaire de recherche). Bien que le codage explicite d'un tel comportement soit plus judicieux.

0 votes

Malheureusement, Rasmus a fait des commentaires à ce sujet en 2009, et pourtant $_REQUEST est essentiellement le même maintenant, en 2015.

10voto

Luca Matteis Points 19338

$_REQUEST fait référence à toutes sortes de requêtes (GET, POST etc..). C'est parfois utile, mais il est généralement préférable de spécifier la méthode exacte ($_GET, $_POST etc.).

19 votes

Cette réponse décrit ce qu'est $_REQUEST, mais elle ne répond pas à la question.

1 votes

Il dit que c'est une meilleure pratique de savoir quel type de demande sera reçue et de coder en fonction de cette demande spécifique.

10voto

Dereleased Points 6187

$_REQUEST est généralement considéré comme nuisible pour la même raison que les transformations de données simples à moyennement complexes sont souvent effectuées dans le code de l'application au lieu d'être déclarées en SQL : certains programmeurs sont nuls.

Ainsi, si l'on a tendance à utiliser $_REQUEST partout, je peux faire via GET tout ce que je pouvais faire via POST, ce qui implique de configurer <img> sur mon site (malveillant) qui amènent les utilisateurs connectés à votre module de commerce électronique à acheter des produits en silence, ou je peux les amener à cliquer sur des liens qui entraîneront des actions dangereuses ou la révélation d'informations sensibles (probablement pour moi).

Toutefois, cela est dû au fait qu'un programmeur PHP novice, ou du moins inexpérimenté, commet des erreurs simples. Tout d'abord, sachez quand les données de quel type sont appropriées. Par exemple, j'ai un service web qui peut renvoyer des réponses en URLEncoding, XML ou JSON. L'application décide du format de la réponse en vérifiant l'en-tête HTTP_ACCEPT, mais peut être contrainte à un format spécifique en envoyant l'en-tête format paramètre.

Lors de la vérification du contenu du paramètre de format, celui-ci peut être envoyé via une querystring ou un postdata, en fonction d'une multitude de facteurs, dont le moindre n'est pas de savoir si les applications appelantes veulent ou non que "&format=json" soit mélangé à leur requête. Dans ce cas, $_REQUEST est très pratique car il m'évite d'avoir à taper quelque chose comme ça :

$format = isset($_POST['format']) ? $_POST['format'] 
    : (isset($_GET['format']) ? $_GET['format'] : null);

Je ne vais pas m'étendre davantage, mais il suffit de dire que $_REQUEST L'usage n'est pas dissuadé parce qu'il est intrinsèquement dangereux - c'est juste un autre outil qui fait exactement ce qu'on lui demande, que vous compreniez ces implications ou non - c'est la décision pauvre, paresseuse ou non informée d'un programmeur pauvre, paresseux ou inexpérimenté qui cause ce problème.

Mode d'emploi $_REQUEST en toute sécurité


  1. Connaître ses données : Vous devriez avoir une certaine attente quant au type de données que vous obtiendrez, et les assainir en conséquence. Des données pour une base de données ? addslashes() o *_escape_string() . Vous allez le montrer à l'utilisateur ? htmlentities() o htmlspecialchars() . Vous attendez des données numériques ? is_numeric() o ctype_digit() . En effet, filter_input() et ses fonctions connexes ne sont conçues que pour vérifier et assainir les données. Utilisez ces outils, toujours.
  2. N'accédez pas directement aux données superglobales fournies par l'utilisateur. . Prenez l'habitude de nettoyer vos données, à chaque fois, et déplacez vos données vers des variables propres, même si c'est juste $post_clean . Vous pouvez également nettoyer directement dans les superglobales, mais la raison pour laquelle je préconise l'utilisation d'une variable distincte est que cela permet de repérer plus facilement les vulnérabilités dans le code, comme le montre l'exemple suivant tout ce qui est pointer directement vers un superglobal et non vers son équivalent aseptisé est considéré comme une erreur dangereuse.
  3. Sachez d'où doivent provenir vos données. Si l'on se réfère à mon exemple ci-dessus, il est tout à fait raisonnable de permettre à la variable "format de réponse" d'être envoyée via GET ou POST. J'autorise également la variable "action" à être envoyée par l'une ou l'autre méthode. Cependant, les actions elles-mêmes ont des exigences très spécifiques quant au verbe HTTP acceptable. . Les fonctions, par exemple, qui apportent des modifications aux données utilisées par le service ne peuvent être envoyées que par POST. Les demandes concernant certains types de données sans privilège ou à faible privilège (telles que des images de cartes générées dynamiquement) peuvent être servies en réponse à des demandes provenant des deux méthodes.

En conclusion, retenez cette règle simple :

LA SÉCURITÉ EST CE QUE VOUS EN FAITES, LES GENS !

EDIT :

I fortement Je vous recommande le conseil de Bobince : si vous le pouvez, réglez les request_order dans le php.ini sur "GP", c'est-à-dire sans composant de cookie. Il n'y a pratiquement aucun raisonnement rationnel pour cela dans plus de 98 % des cas, car les données des cookies ne devraient presque jamais être considérées comme comparables à la chaîne de requête ou aux postdonnées.

P.S., Anecdote !

J'ai connu un programmeur qui a pensé à $_REQUEST un endroit pour stocker simplement des données accessibles de manière superglobale. Des noms d'utilisateur et des mots de passe importants, des chemins d'accès à des fichiers, etc. $_REQUEST . Il a été un peu surpris (mais pas de façon comique, malheureusement) lorsque je lui ai expliqué le comportement de cette variable. Inutile de dire que cette pratique a été abandonnée.

8voto

Ben James Points 41165

Les demandes GET doivent être idempotentes et les demandes POST ne le sont généralement pas. Cela signifie que les données dans $_GET y $_POST doivent généralement être utilisés de manière différente.

Si votre application utilise des données provenant de $_REQUEST il se comportera de la même manière pour les demandes GET et POST, ce qui viole l'idempotence de GET.

1 votes

Mais cela ne dépend-il pas de l'implémentation ? "Indempotent" est un mot nouveau pour moi, mais si je le comprends bien, il serait facile d'imaginer la mise en place d'une situation GET qui ne soit pas indempotente. Par exemple, les compteurs de pages augmentent généralement chaque fois que vous demandez une url donnée.

1 votes

@sprugman - de même, il peut y avoir des situations où vous avez à la fois des données GET et des données d'entrée. et POST dans la même demande, auquel cas la méthode de demande est essentiellement dénuée de sens lorsqu'elle est mise en contexte avec les données de la demande.

0 votes

Sprugman, évidemment toute requête GET modifie quelque chose car elle est enregistrée par le serveur web. Il peut encore être indemne dans le domaine de l'application, où ces métadonnées n'ont pas vraiment d'importance.

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