¿Qué pasa con el uso de $ _REQUEST ?

He visto una serie de publicaciones aquí que dicen que no se debe usar la variable $_REQUEST . Normalmente no, pero a veces es conveniente. ¿Qué pasa con eso?

No hay absolutamente nada de malo en recibir información de $_GET y $_POST de forma combinada. De hecho, eso es lo que casi siempre quieres hacer:

  • para una solicitud simple idempotente generalmente presentada a través de GET, existe la posibilidad de que la cantidad de datos que desea no se ajuste a una URL, por lo que se ha mutado a una solicitud POST en su lugar como una cuestión práctica.

  • para una solicitud que tenga un efecto real, debe verificar que haya sido enviado por el método POST. Pero la forma de hacerlo es comprobar $_SERVER['REQUEST_METHOD'] explícitamente, no confiar en que $_POST esté vacío para un GET. Y, de todos modos, si el método es POST , puede que desee eliminar algunos parámetros de consulta de la URL.

No, el problema con $_REQUEST no tiene nada que ver con la combinación de los parámetros GET y POST. Es que también, por defecto, incluye $_COOKIE . Y las cookies realmente no son para nada parámetros de envío de formularios: casi nunca desea tratarlos como lo mismo.

Si accidentalmente obtiene un conjunto de cookies en su sitio con el mismo nombre que uno de los parámetros de su formulario, los formularios que dependen de ese parámetro dejarán de funcionar misteriosamente debido a que los valores de las cookies anulan los parámetros esperados. Esto es muy fácil de hacer si tiene múltiples aplicaciones en el mismo sitio, y puede ser muy difícil depurarlo cuando solo tiene un par de usuarios con cookies antiguas, ya no usa más y rompe los formularios de forma que no -uno más puede reproducirse.

Puede cambiar este comportamiento al orden GP mucho más sensible (sin C ) con la configuración request_order en PHP 5.3. Cuando esto no sea posible, yo personalmente evitaría $_REQUEST y, si necesito un conjunto combinado GET + POST, $_REQUEST manualmente.

Estuve investigando algunas publicaciones de grupos de noticias en PHP Internals y encontré una discusión interesante sobre el tema. El hilo inicial era sobre otra cosa, pero un comentario de Stefan Esser, un experto en seguridad (si no el ) en el mundo PHP, dirigió la discusión hacia las implicaciones de seguridad de usar $ _REQUEST para algunas publicaciones.

Citando a Stefan Esser en PHP Internals

$ _REQUEST es una de las mayores debilidades de diseño en PHP. Cada aplicación que usa $ _REQUEST es muy probablemente vulnerable a los problemas de Delayed Cross Site Forgery. (Esto básicamente significa que si, por ejemplo, existe una cookie llamada (edad) siempre sobrescribirá el contenido GET / POST y, por lo tanto, se realizarán solicitudes no deseadas)

y en una respuesta posterior al mismo hilo

No se trata del hecho de que alguien pueda forjar GET, POST; Variables COOKIE. Se trata del hecho de que los COOKIE sobrescribirán los datos GET y POST en REQUEST.

Por lo tanto, puedo infectar tu navegador con una cookie que dice, por ejemplo, acción = cerrar sesión y desde ese día ya no puedes usar la aplicación porque SOLICITUD [acción] cerrará la sesión para siempre (hasta que elimines la cookie manualmente).

Y contagiarte con un COOKIE es tan simple …
a) Podría usar un XSS vuln en cualquier aplicación en un subdominio
b) ¿Has intentado alguna vez establecer una cookie para * .co.uk o * .co.kr cuando tienes un solo dominio allí?
c) Otro dominio cruzado de cualquier forma …

Y si crees que esto no es un problema, puedo decirte que hay una posibilidad simple de configurar una cookie * .co.kr que tenga como resultado varias versiones de PHP que solo devuelven páginas en blanco. Imagine: solo una cookie para matar todas las páginas de PHP en * .co.kr

Y al establecer una ID de sesión ilegal en una cookie válida para * .co.kr en una variable llamada + PHPSESSID = ilegal , todavía puede DOS cada aplicación de PHP en Corea utilizando sesiones de PHP …

La discusión continúa por algunas publicaciones más y es interesante de leer.


Como puede ver, el principal problema con $ _REQUEST no es tanto que tenga datos de $ _GET y $ _POST, sino también de $ _COOKIE. Algunos otros tipos en la lista sugirieron cambiar el orden en que $ _REQUEST está lleno, por ejemplo llenándolo con $ _COOKIE primero, pero esto podría conducir a muchos otros problemas potenciales, por ejemplo, con el manejo de la sesión .

Sin embargo, puede omitir $ _COOKIES del $ _REQUEST global, para que no se sobrescriba con ninguna de las otras matrices (de hecho, puede limitarlo a cualquier combinación de sus contenidos estándar, como el manual de PHP en la configuración variable_order ini Cuéntanos:

variable_order Establece el orden del análisis de la variable EGPCS (Entorno, Obtener, Publicación, Cookie y Servidor). Por ejemplo, si variables_order está establecido en “SP”, PHP creará los superglobales $ _SERVER y $ _POST, pero no creará $ _ENV, $ _GET, y $ _COOKIE. Establecer en “” significa que no se establecerán superglobales.

Pero, una vez más, también podría considerar no usar $ _REQUEST por completo, simplemente porque en PHP puede acceder a Entorno, Obtener, Publicar, Cookie y Servidor en sus propios elementos globales y tener un vector de ataque menos. Todavía tiene que desinfectar estos datos, pero es una cosa menos de la que preocuparse.


Ahora se puede preguntar, ¿por qué $ _REQUEST existe después de todo y por qué no se elimina? Esto también se preguntó en PHP Internals. Citando a Rasmus Lerdorf sobre ¿Por qué existe $ _REQUEST? en PHP Internals

Cuantas más cosas como esta eliminemos, más difícil será para las personas pasar rápidamente a las versiones más nuevas, más rápidas y más seguras de PHP. Eso causa más frustración para todos que unas pocas características heredadas “feas”. Si hay una razón técnica decente, rendimiento o seguridad, entonces debemos analizarla detenidamente. En este caso, lo que deberíamos observar no es si deberíamos eliminar $ _REQUEST, sino si deberíamos eliminar los datos de las cookies de él. Muchas configuraciones ya lo hacen, incluso todas las mías, y existe una fuerte razón de seguridad válida para no incluir cookies en $ _REQUEST. La mayoría de las personas usa $ _REQUEST para referirse a GET o POST, sin darse cuenta de que también podría contener cookies y, como tales, los tipos malos podrían hacer algunos trucos de inyección de cookies y romper aplicaciones ingenuas.

De todos modos, espero que arroje algo de luz.

$_REQUEST refiere a todo tipo de solicitudes (GET, POST, etc.). Esto a veces es útil, pero generalmente es mejor especificar el método exacto ($ _GET, $ _POST, etc.).

$_REQUEST generalmente se considera dañino por la misma razón que las transformaciones de datos de complejidad simple a mediana a menudo se realizan en el código de la aplicación en lugar de declararse en SQL: algunos progtwigdores apestan.

Como tal, si uno tiende a usar $_REQUEST todas partes, puedo hacer cualquier cosa a través de GET que pueda a través de POST, lo que significa configurar tags en mi sitio (malicioso) que provocan que los usuarios que inicien sesión en su módulo de comercio electrónico compren productos silenciosamente, o puedo hacer que hagan clic en enlaces que darán lugar a acciones peligrosas o la revelación de información sensible (probablemente para mí).

Sin embargo, esto se debe a que un progtwigdor PHP novato, o al menos inexperto, comete errores simples. En primer lugar, saber cuándo los datos de qué tipo es apropiado. Por ejemplo, tengo un servicio web que puede devolver respuestas en URLEncoding, XML o JSON. La aplicación decide cómo formatear la respuesta comprobando el encabezado HTTP_ACCEPT, pero puede forzarse en uno específicamente enviando el parámetro de format .

Al verificar el contenido del parámetro de formato, podría enviarse a través de una cadena de consulta o un postdata, dependiendo de una multitud de factores, entre los que se encuentra si las aplicaciones llamantes quieren que “& format = json” se mezcle con su solicitud. En este caso, $_REQUEST es muy conveniente porque me ahorra tener que escribir algo como esto:

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

No voy a dar vueltas mucho más lejos, pero basta con decir que el uso de $_REQUEST no se disuade porque es intrínsecamente peligroso; es solo otra herramienta que hace exactamente lo que se le pide, ya sea que comprenda o no esas implicaciones. es la decisión pobre, floja o desinformada de un progtwigdor pobre, perezoso o inexperto que causa este problema.

Cómo usar $_REQUEST forma segura


  1. Conozca sus datos : debe tener alguna expectativa sobre qué tipo de datos obtendrá, así que desinfecte en consecuencia. Datos para una base de datos? addslashes() o *_escape_string() . ¿Volver a mostrarlo al usuario? htmlentities() o htmlspecialchars() . Esperando datos numéricos? is_numeric() o ctype_digit() . De hecho, filter_input() y sus funciones relacionadas están diseñadas para hacer nada más que verificar y desinfectar los datos. Usa estas herramientas, siempre.
  2. No acceda directamente a los datos de superglobales de los usuarios . Adquiera el hábito de desinfectar sus datos, cada vez, y mueva sus datos a variables de limpieza, incluso si solo es $post_clean . Alternativamente, puedes simplemente limpiar directamente en los superglobales, pero la razón por la que abogar por el uso de una variable separada es porque al hacerlo es fácil detectar vulnerabilidades en el código, ya que cualquier cosa que apunte directamente a un superglobal y no a su equivalente sanitizado se considera un error peligroso .
  3. Sepa de dónde deberían venir los datos. Al hacer referencia a mi ejemplo anterior, es perfectamente razonable permitir que la variable de formato de respuesta se envíe a través de GET o POST. También permito que la variable “acción” sea enviada a través de cualquier método. Sin embargo, las acciones en sí tienen requisitos muy específicos sobre qué verbo HTTP es aceptable . Las funciones, por ejemplo, que realizan cambios en los datos utilizados por el servicio solo se pueden enviar a través de POST. Las solicitudes de ciertos tipos de datos de privilegios bajos o no (como las imágenes de mapas generadas dinámicamente) se pueden servir en respuesta a las solicitudes de cualquiera de los métodos.

En conclusión, recuerda esta simple regla:

¡LA SEGURIDAD ES LO QUE LO HACES, PERSONAS!

EDITAR:

Recomiendo encarecidamente los consejos de Bobince: si puede, establezca el parámetro request_order en php.ini en “GP”; es decir, ningún componente de cookie. Casi no existe un razonamiento racional para esto en el 98% + de los casos, ya que los datos de las cookies casi nunca deberían considerarse comparables a la cadena de consulta o a los datos de postdata.

PD, anécdota!

Conocí a un progtwigdor que pensó en $_REQUEST un lugar para simplemente almacenar datos accesibles de forma superglobal. Nombres de usuario y contraseñas importantes, rutas a archivos, lo que sea, y se almacenó en $_REQUEST . Estaba un poco sorprendido (aunque no cómicamente, desafortunadamente) cuando le conté cómo se comporta esa variable. Huelga decir que esa práctica ha sido depuesta.

Las solicitudes GET deben ser idempotentes y las solicitudes POST generalmente no. Esto significa que los datos en $_GET y $_POST generalmente se deben usar de diferentes maneras.

Si su aplicación está utilizando datos de $_REQUEST , se comportará igual para las solicitudes GET y POST, lo que viola la idempotencia de GET.

Es vago Realmente no sabe cómo le llegaron los datos, ya que lleva datos de publicación, obtención y cookie. No necesariamente creo que eso siempre sea malo, a menos que necesite saber o restringir el método de entrega.

De hecho, me gusta usarlo. Le da la flexibilidad de usar GET o POST que puede ser útil para cosas como formularios de búsqueda donde la mayoría de los datos están POSTADOS, pero a veces querrá decir un enlace a una búsqueda particular, para que pueda usar parámetros GET en su lugar .

Además, si observa muchos otros lenguajes (ASP.NET por ejemplo) no hacen ninguna distinción entre las variables GET y POST.

ETA :

Nunca utilicé REQUEST para obtener los valores de COOKIE, pero creo que Kyle Butt hace un gran comentario en este comentario. NO es una buena idea usar SOLICITUD para obtener los valores de COOKIE. Creo que tiene razón en que hay un potencial real para la falsificación de solicitudes entre sitios si lo haces.

Además, el orden en que las cosas se cargan en REQUEST se controla mediante los parámetros de configuración en php.ini (variables_order y request_order). Entonces, si tiene la misma variable pasada a través de POST y GET, la que realmente ingresa a PETICIÓN depende de esas configuraciones ini. Esto podría afectar la portabilidad si depende de un pedido en particular y esas configuraciones están configuradas de forma diferente a lo que esperaba.

Es importante entender cuándo usar POST, cuándo usar GET y cuándo usar una cookie. Con $ _REQUEST, el valor que está viendo podría provenir de cualquiera de ellos. Si espera obtener el valor de un POST o un GET o de una COOKIE, es más informativo que alguien que lea su código use la variable específica en lugar de $ _REQUEST.

Otra persona señaló también que no desea que todas las POST o cookies sean anuladas por GET porque existen diferentes reglas entre sitios para todas ellas, por ejemplo, si devuelve datos ajax mientras usa $ _REQUEST, es vulnerable a un ataque de script de sitio cruzado.

La única vez que usa $_REQUEST no es una mala idea es con GET.

  • Si lo usa para cargar valores POST, corre el riesgo de falsificaciones de solicitudes entre sitios
  • Si lo usa para cargar valores de cookies, corre nuevamente el riesgo de falsificaciones de solicitudes entre sitios

E incluso con GET, $_GET es más corto de escribir que $_REQUEST 😉

Puede que solo se use si desea recuperar la URL actual o el nombre de host, pero para analizar los datos de esa URL, como los parámetros que usan el símbolo &, probablemente no sea una buena idea. En general, no desea utilizar una descripción vaga de lo que está tratando de hacer. Si necesita especificar que es donde $ _REQUEST es malo, si no necesita ser específico, siéntase libre de usarlo. Pensaría.

Si sabe qué datos quiere, explíquelos. IMO, GET y POST son dos animales diferentes y no puedo pensar en una buena razón por la que alguna vez necesitarías mezclar datos de publicaciones y cadenas de consulta. Si alguien tiene uno, estaría interesado.

Puede ser conveniente usar $ _REQUEST cuando sus scripts puedan responder a GET o POST de la misma manera. Sin embargo, yo diría que este debería ser un caso extremadamente raro, y en la mayoría de los casos, se prefieren dos funciones separadas para manejar dos conceptos separados, o al menos verificar el método y seleccionar las variables correctas. El flujo de progtwigs suele ser mucho más fácil de seguir cuando no es necesario hacer referencia cruzada de dónde pueden venir las variables. Sea amable con la persona que debe mantener su código dentro de 6 meses. Podría ser tu.

Además de los problemas de seguridad y WTF causados ​​por las cookies y las variables de entorno en la variable REQUEST (no me inicie en GLOBAL), considere lo que podría suceder en el futuro si PHP comenzara a apoyar nativamente otros métodos, como PUT y DELETE. Si bien es muy poco probable que estos se fusionen en REQUEST superglobal, es posible que se puedan incluir como opción en la configuración variable_order. Entonces, realmente no tienes ni idea de qué SOLICITUD tiene y qué es lo que está tomando precedencia, particularmente si tu código se implementa en un servidor de terceros.

¿POST es más seguro que GET? Realmente no. Es mejor usar GET cuando sea práctico porque es más fácil ver en sus registros cómo se está explotando su aplicación cuando es atacada. POST es mejor para las operaciones que afectan el estado del dominio porque las arañas generalmente no las siguen, y los mecanismos de búsqueda predictiva no eliminarán todo su contenido cuando inicie sesión en su CMS. Sin embargo, la pregunta no era sobre los méritos de GET versus POST, sino sobre cómo el receptor debería tratar los datos entrantes y por qué es malo fusionarlos, por lo que esto es realmente solo un error.

Creo que no hay problema con $_REQUEST , pero debemos tener cuidado al usarlo ya que es una colección de variables de 3 fonts (GPC).

Supongo que $_REQUEST todavía está disponible para hacer que los viejos progtwigs sean compatibles con las nuevas versiones de php, pero si comenzamos nuevos proyectos (incluidas nuevas bibliotecas), creo que no deberíamos usar $_REQUEST para hacer que los progtwigs sean más claros. Incluso deberíamos considerar eliminar usos de $_REQUEST y reemplazarlos con una función de contenedor para hacer que el progtwig sea más claro, especialmente en el procesamiento de datos de texto enviados grandes, ya que $_REQUEST contiene copias de $_POST .

 // delete $_REQUEST when program execute, the program would be lighter // when large text submitted unset($_REQUEST); // wrapper function to get request var function GetRequest($key, $default = null, $source = '') { if ($source == 'get') { if (isset($_GET[$key])) { return $_GET[$key]; } else { return $default; } } else if ($source == 'post') { if (isset($_POST[$key])) { return $_POST[$key]; } else { return $default; } } else if ($source == 'cookie') { if (isset($_COOKIE[$key])) { return $_COOKIE[$key]; } else { return $default; } } else { // no source specified, then find in GPC if (isset($_GET[$key])) { return $_GET[$key]; } else if (isset($_POST[$key])) { return $_POST[$key]; } else if (isset($_COOKIE[$key])) { return $_COOKIE[$key]; } else { return $default; } } } 

Darren Cook: “Desde php 5.3 el php.ini predeterminado dice que solo los datos GET y POST se ponen en $_REQUEST . Ver php.net/request_order Acabo de tropezar con este salto de compatibilidad hacia atrás cuando esperaba que los datos de las cookies estuvieran en $_REQUEST y me preguntaba ¡Por qué no estaba funcionando!

Guau … solo algunos de mis scripts dejaron de funcionar debido a una actualización a PHP 5.3 . Hizo lo mismo: suponga que las cookies se establecerán al usar la variable $_REQUEST . Con la actualización exactamente eso dejó de funcionar.

Ahora llamo valores de cookies por separado usando $_COOKIE["Cookie_name"]

Es muy inseguro. También es incómodo ya que no sabe si está recibiendo un POST o un GET u otra solicitud. Deberías saber la diferencia entre ellos cuando diseñas tus aplicaciones. GET es muy inseguro ya que se transmite en la URL y no es adecuado para casi nada además de la navegación de página. POST, aunque no es seguro por sí solo, proporciona un nivel de seguridad.