¿Qué variables $ _SERVER son seguras?

97

Cualquier variable que un usuario pueda controlar, un atacante también puede controlar y, por tanto, es fuente de un ataque. Esto se denomina variable "contaminada" y no es segura.

Cuando se usa $_SERVER, se pueden controlar muchas de las variables. PHP_SELF, HTTP_USER_AGENT, HTTP_X_FORWARDED_FOR, HTTP_ACCEPT_LANGUAGEY muchos otros son una parte de la cabecera de petición HTTP enviada por el cliente.

¿Alguien sabe de una "lista segura" o una lista no contaminada de $_SERVERvariables?

torre
fuente
8
Depende de cómo defina "seguro". Los valores son seguros tal como son, solo depende para qué los use.
diciembre
6
Creo que en este contexto, Rook está diciendo "Qué variables de servidor no pueden ser falsificadas por el usuario", como REMOTE_ADDR.
vcsjones
6
Todo lo que HTTP_esté precedido por un encabezado de solicitud y puede ser configurado por el navegador o el proxy intermedio. Los consideraría como cualquier otra entrada del usuario.
datasage
3
@ bob-the-destroyer REMOTE_ADDR se extrae directamente del socket TCP de apache, este valor no se puede falsificar a través de Internet debido al protocolo de enlace de tres vías.
torre
2
@Rook: buen punto. Supongo que con la mención de "spoofing", me inclinaba más hacia el antiguo acto de spoofing de ip en sí mismo, en lugar de cualquier tipo de falsificación del valor real de REMOTE_ADDR. Y eso estaría fuera del alcance de esta pregunta. Sin embargo, es bueno tener una idea de cómo se establece este valor, así que gracias.
bob-the-destroyer

Respuestas:

147

No existen valores "seguros" o "inseguros" como tales. Solo hay valores que controla el servidor y valores que controla el usuario, y debe saber de dónde proviene un valor y, por lo tanto, si se puede confiar en él para un determinado propósito.$_SERVER['HTTP_FOOBAR']por ejemplo, es completamente seguro almacenarlo en una base de datos, pero ciertamente no evallo haría .

Como tal, dividamos esos valores en tres categorías:

Controlado por servidor

Estas variables las establece el entorno del servidor y dependen completamente de la configuración del servidor.

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

Parcialmente controlado por el servidor

Estas variables dependen de la solicitud específica que envió el cliente, pero solo pueden tomar un número limitado de valores válidos, ya que todos los valores inválidos deben ser rechazados por el servidor web y no causar que se inicie la invocación del script. Por tanto, pueden considerarse fiables .

  • 'HTTPS'
  • 'REQUEST_TIME'
  • 'REMOTE_ADDR' *
  • 'REMOTE_HOST' *
  • 'REMOTE_PORT' *
  • 'SERVER_PROTOCOL'
  • 'HTTP_HOST'
  • 'SERVER_NAME'
  • 'SCRIPT_FILENAME'
  • 'SERVER_PORT'
  • 'SCRIPT_NAME'

* Se REMOTE_garantiza que los valores son la dirección válida del cliente, como se verifica mediante un protocolo de enlace TCP / IP. Esta es la dirección a la que se enviará cualquier respuesta. REMOTE_HOSTSin embargo, se basa en búsquedas de DNS inversas y, por lo tanto, puede ser falsificado por ataques de DNS contra su servidor (en cuyo caso, de todos modos, tiene problemas mayores). Este valor puede ser un proxy, que es una simple realidad del protocolo TCP / IP y nada sobre lo que pueda hacer nada.

† Si su servidor web responde a cualquier solicitud independientemente del HOSTencabezado, esto también debe considerarse inseguro. Consulte ¿Qué tan seguro es $ _SERVER [“HTTP_HOST”]? .
Consulte también http://shiflett.org/blog/2006/mar/server-name-versus-http-host .

‡ Consulte https://bugs.php.net/bug.php?id=64457 , http://httpd.apache.org/docs/current/mod/core.html#usecanonicalphysicalport , http: //httpd.apache. org / docs / 2.4 / mod / core.html # comment_999

Valores totalmente arbitrarios controlados por el usuario

Estos valores no se comprueban en absoluto y no dependen de ninguna configuración del servidor, son información totalmente arbitraria enviada por el cliente.

  • 'argv', 'argc'(solo se aplica a la invocación de CLI, no suele ser una preocupación para los servidores 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' (puede contener datos contaminados)
  • 'PHP_SELF' (puede contener datos contaminados)
  • 'PATH_TRANSLATED'
  • cualquier otro 'HTTP_'valor

§ Puede ser considerado confiable siempre que el servidor web permita solo ciertos métodos de solicitud.

‖ Puede ser considerado confiable si la autenticación es manejada completamente por el servidor web.

La superglobal $_SERVERtambién incluye varias variables de entorno. Que sean "seguros" o no dependerá de cómo (y dónde) se definan. Pueden variar desde completamente controlados por el servidor hasta completamente controlados por el usuario.

deceze
fuente
3
@Rook Pero como dije, depende absolutamente de cómo lo uses . Los valores por sí mismos no son seguros ni inseguros, depende de para qué los use . Incluso los datos enviados por un usuario infame están perfectamente seguros siempre que no haga nada con ellos que pueda comprometer su seguridad.
diciembre
2
@Rook: tu idea de "seguro" hace que esta pregunta parezca un poco arbitraria, especialmente porque está completamente vinculada a una extensión oscura o una versión personalizada de PHP. Si bien dice "no debería tener un enfoque de" disparar desde la cadera ", cualquier respuesta en realidad parece requerir un mínimo de familiaridad con el código fuente PHP para averiguar cómo se establecen estos valores. ¿Enviar correos electrónicos a los desarrolladores de PHP no sería un mejor enfoque para encontrar una respuesta?
bob-the-destroyer
2
@Rook: falta de comunicación. Como insinuó Dezeze, "seguro para qué propósito". Como indiqué, se desconoce su propósito y, además, hay varios otros $_SERVERvalores no documentados dependiendo de cómo se entregue el archivo. En mi opinión, los documentados no aclaran la verdadera fuente. De lo contrario, creo que no estaría haciendo esta pregunta. Me alegro de que tenga una lista que pueda usar. Pero aún así sugeriría enviar un informe de errores (cuando se solucione su sitio de errores), enviar un correo electrónico a los mantenedores de documentos o actualizar los documentos usted mismo (si está al tanto del enlace). Sería beneficioso para la comunidad conocer esta información.
bob-the-destroyer
3
SERVER_NAMEno está necesariamente controlado por el servidor. Dependiendo de la puerta de enlace y la configuración, puede estar duplicado HTTP_HOSTy, por lo tanto, sujeto a la misma advertencia.
Bobince
1
@deceze @Rook ¿ SERVER_PORTNecesita esa pequeña cruz? bugs.php.net/bug.php?id=64457
Dejan Marjanović
12

En PHP, cada $_SERVERvariable que comience con HTTP_puede ser influenciada por el usuario. Por ejemplo, la variable $_SERVER['HTTP_REINERS']puede estar contaminada configurando el encabezado HTTP REINERSen un valor arbitrario en la solicitud HTTP.

Reiners
fuente
re "arbitrario"; No del todo arbitrarios, ya que se ajustan a un formato. Por ejemplo, $_SERVER['HTTP_REINERS'] no puede contener caracteres de nueva línea en la mayoría de sapis.
Pacerier