w3schools usar sirve request_uri que php_self para http_referer ejemplo dominio como capturar _server php apache security owasp

usar - PHP $_SERVER[''HTTP_HOST''] vs. $_SERVER[''SERVER_NAME''], ¿entiendo las páginas man correctamente?



para que sirve $_ server['' http_referer ''] (8)

Realicé muchas búsquedas y también leí los documentos PHP $_SERVER . ¿Tengo este derecho con respecto a qué utilizar para mis scripts PHP para las definiciones de enlaces simples que se usan en todo mi sitio?

$_SERVER[''SERVER_NAME''] se basa en el archivo de configuración de los servidores web (Apache2 en mi caso), y varía según unas pocas directivas: (1) VirtualHost, (2) ServerName, (3) UseCanonicalName, etc.

$_SERVER[''HTTP_HOST''] se basa en la solicitud del cliente.

Por lo tanto, me parece que el más adecuado para hacer que mis scripts sean lo más compatibles posibles sería $_SERVER[''HTTP_HOST''] . ¿Es correcta esta suposición?

Comentarios de seguimiento:

Supongo que me puse un poco paranoico después de leer este artículo y de que algunas personas dijeron que "no confiarían en ninguno de los $_SERVER vars":

Aparentemente la discusión es principalmente sobre $_SERVER[''PHP_SELF''] y por qué no debes usarlo en el atributo de acción de forma sin un escape adecuado para prevenir ataques XSS.

Mi conclusión sobre mi pregunta original anterior es que es "seguro" usar $_SERVER[''HTTP_HOST''] para todos los enlaces en un sitio sin tener que preocuparse por los ataques XSS, incluso cuando se usan en formularios.

Por favor corrígeme si estoy equivocado.


¿Es "seguro" usar $_SERVER[''HTTP_HOST''] para todos los enlaces en un sitio sin tener que preocuparse por los ataques XSS, incluso cuando se usan en formularios?

Sí, es safe usar $_SERVER[''HTTP_HOST''] , (e incluso $_GET y $_POST ) siempre que los verifique antes de aceptarlos. Esto es lo que hago para servidores de producción seguros:

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ $reject_request = true; if(array_key_exists(''HTTP_HOST'', $_SERVER)){ $host_name = $_SERVER[''HTTP_HOST'']; // [ need to cater for `host:port` since some "buggy" SAPI(s) have been known to return the port too, see http://goo.gl/bFrbCO $strpos = strpos($host_name, '':''); if($strpos !== false){ $host_name = substr($host_name, $strpos); } // ] // [ for dynamic verification, replace this chunk with db/file/curl queries $reject_request = !array_key_exists($host_name, array( ''a.com'' => null, ''a.a.com'' => null, ''b.com'' => null, ''b.b.com'' => null )); // ] } if($reject_request){ // log errors // display errors (optional) exit; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ echo ''Hello World!''; // ...

La ventaja de $_SERVER[''HTTP_HOST''] es que su comportamiento está mejor definido que $_SERVER[''SERVER_NAME''] . Contraste ➫➫ :

Contenido del encabezado Host: de la solicitud actual, si hay uno.

con:

El nombre del host del servidor bajo el cual se está ejecutando el script actual.

El uso de una interfaz mejor definida como $_SERVER[''HTTP_HOST''] significa que más SAPIs lo implementarán utilizando un comportamiento confiable y bien definido. (A diferencia del otro .) Sin embargo, todavía depende totalmente de SAPI ➫➫ :

No hay garantía de que cada servidor web proporcione cualquiera de estas [ $_SERVER entradas]; los servidores pueden omitir algunos, o proporcionar otros que no se enumeran aquí.

Para comprender cómo recuperar correctamente el nombre de host, lo primero y más importante es comprender que un servidor que solo contiene código no tiene forma de saber (requisito previo para verificar) su propio nombre en la red. Necesita interactuar con un componente que le proporciona su propio nombre. Esto se puede hacer a través de:

  • archivo de configuración local

  • base de datos local

  • código fuente codificado

  • solicitud externa ( curl )

  • Host: del cliente / atacante Host: solicitud

  • etc

Por lo general, se realiza a través del archivo de configuración local (SAPI). Tenga en cuenta que lo ha configurado correctamente, por ejemplo, en Apache ➫➫ :

Hay que "falsificar" algunas cosas para que el host virtual dinámico se vea como uno normal.

El más importante es el nombre del servidor que Apache utiliza para generar URL autorreferenciales, etc. Está configurado con la directiva ServerName , y está disponible para los CGI a través de la variable de entorno SERVER_NAME .

El valor real utilizado en el tiempo de ejecución se controla mediante la configuración UseCanonicalName.

Con UseCanonicalName Off el nombre del servidor proviene del contenido del encabezado Host: en la solicitud. Con UseCanonicalName DNS proviene de una búsqueda DNS inversa de la dirección IP del host virtual. La configuración anterior se utiliza para el alojamiento virtual dinámico basado en nombre, y la última se utiliza para el alojamiento ** basado en IP.

Si Apache no puede encontrar el nombre del servidor porque no hay un encabezado Host: o la búsqueda DNS falla, entonces se usa el valor configurado con ServerName .


Esta es una traducción detallada de lo que Symfony usa para obtener el nombre de host ( vea el segundo ejemplo para una traducción más literal ):

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); }

Anticuado:

Esta es mi traducción al PHP desnudo de un método utilizado en Symfony framework que intenta obtener el nombre de host de todas las formas posibles en orden de mejores prácticas:

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); }


La principal diferencia entre los dos es que $_SERVER[''SERVER_NAME''] es una variable controlada por el servidor, mientras que $_SERVER[''HTTP_HOST''] es un valor controlado por el usuario.

La regla de oro es no confiar nunca en los valores del usuario, por lo que $_SERVER[''SERVER_NAME''] es la mejor opción.

Como Gumbo señaló, Apache construirá SERVER_NAME a partir de los valores proporcionados por el usuario si no configura UseCanonicalName On .

Editar: Dicho todo esto, si el sitio utiliza un host virtual basado en el nombre, el encabezado del host HTTP es la única forma de llegar a los sitios que no son el sitio predeterminado.


No estoy seguro y no confío realmente en $_SERVER[''HTTP_HOST''] porque depende del encabezado del cliente. De otra manera, si un dominio solicitado por el cliente no es el mío, no entrarán en mi sitio porque el protocolo DNS y TCP / IP lo señalan al destino correcto. Sin embargo, no sé si es posible secuestrar el DNS, la red o incluso el servidor Apache. Para estar seguro, defino el nombre de host en el entorno y lo comparo con $_SERVER[''HTTP_HOST''] .

Agregue SetEnv MyHost domain.com en el archivo .htaccess en la raíz y agregue el código ths en Common.php

if (getenv(''MyHost'')!=$_SERVER[''HTTP_HOST'']) { header($_SERVER[''SERVER_PROTOCOL''].'' 400 Bad Request''); exit(); }

Incluí este archivo Common.php en cada página php. Esta página hace todo lo necesario para cada solicitud, como session_start() , modifica la cookie de sesión y rechaza si el método de publicación proviene de un dominio diferente.


Probablemente sea el primer pensamiento de todos. Pero es un poco más difícil. Ver el artículo de Chris Shiflett SERVER_NAME Versus HTTP_HOST .

Parece que no hay una bala de plata. Solo cuando obligue a Apache a usar el nombre canónico , siempre obtendrá el nombre correcto del servidor con SERVER_NAME .

Entonces, o vas con eso o verificas el nombre de host con una lista blanca:

$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; }


Solo una nota adicional: si el servidor se ejecuta en un puerto distinto de 80 (como podría ser habitual en una máquina de desarrollo / intranet), HTTP_HOST contiene el puerto, mientras que SERVER_NAME no.

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

(Al menos eso es lo que he notado en los hosts virtuales basados ​​en el puerto Apache)

Como ha señalado Mike a continuación, HTTP_HOST no contiene :443 cuando se ejecuta en HTTPS (a menos que esté ejecutando en un puerto no estándar, que no he probado).


Utilizar cualquiera. Ambas están igualmente (in) seguras, ya que en muchos casos SERVER_NAME simplemente está lleno de HTTP_HOST de todos modos. Normalmente utilizo HTTP_HOST para que el usuario permanezca en el nombre de host exacto en el que comenzó. Por ejemplo, si tengo el mismo sitio en un dominio .com y .org, no quiero enviar a alguien de .org a .com, especialmente si pueden tener tokens de inicio de sesión en .org que perderían si se envían a el otro dominio.

De cualquier manera, solo necesita asegurarse de que su aplicación web solo responda por dominios conocidos. Esto se puede hacer ya sea (a) con una verificación del lado de la aplicación como la de Gumbo, o (b) utilizando un host virtual en el (los) nombre (s) de dominio que desee que no respondan a las solicitudes que dan un encabezado Host desconocido.

La razón de esto es que si permite acceder a su sitio con cualquier nombre anterior, se expone a ataques de reenlace DNS (donde el nombre de host de otro sitio apunta a su IP, un usuario accede a su sitio con el nombre de host del atacante y luego el nombre de host) se mueve al IP del atacante, tomando sus cookies / auth con él) y el secuestro del motor de búsqueda (donde un atacante señala su propio nombre de host en su sitio e intenta hacer que los motores de búsqueda lo vean como el "mejor" nombre de host primario).

Aparentemente la discusión es principalmente sobre $ _SERVER [''PHP_SELF''] y por qué no debes usarlo en el atributo de acción de forma sin un escape adecuado para prevenir ataques XSS.

Pfft. Bueno, no deberías usar nada en ningún atributo sin escaparte con htmlspecialchars($string, ENT_QUOTES) , por lo que no hay nada especial acerca de las variables del servidor allí.


XSS siempre estará allí, incluso si usa $_SERVER[''HTTP_HOST''] , $_SERVER[''SERVER_NAME''] O $_SERVER[''PHP_SELF'']