Hice mucha búsqueda y también leí los documentos PHP $ _SERVER . ¿Tengo este derecho con respecto a cuál usar para mis scripts PHP para definiciones de enlaces simples usadas en mi sitio?
$_SERVER['SERVER_NAME']
se basa en el archivo de configuración de su servidor web (Apache2 en mi caso) y varía según algunas directivas: (1) VirtualHost, (2) ServerName, (3) UseCanonicalName, etc.
$_SERVER['HTTP_HOST']
se basa en la solicitud del cliente.
Por lo tanto, me parece que sería apropiado utilizarlo para que mis scripts sean lo más compatibles posible $_SERVER['HTTP_HOST']
. ¿Es correcta esta suposición?
Comentarios de seguimiento:
Creo que me puse un poco paranoico después de leer este artículo y notar que algunas personas dijeron "no confiarían en ninguno de los $_SERVER
vars":
http://markjaquith.wordpress.com/2009/09/21/php-server-vars-not-safe-in-forms-or-links/
http://php.net/manual/en/reserved.variables.server.php#89567 (comentario: Vladimir Kornea 14-mar-2009 01:06)
Aparentemente, la discusión es principalmente sobre $_SERVER['PHP_SELF']
y por qué no debe usarlo en el atributo de acción de formulario sin escapar adecuadamente para evitar 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.
$_SERVER['SERVER_NAME']
y$_SERVER['HTTP_HOST']
(aparte de implementar algún otro protocolo de enlace personalizado basado en la solicitud del usuario). Los desarrolladores profesionales no confían en las cosas que no entienden completamente. Por lo tanto, tienen su configuración de SAPI perfectamente correcta (en cuyo caso la opción que usan les dará el resultado correcto), o harán una lista blanca de tal manera que no importa qué valores proporcione el SAPI.array_key_exists
es más escalable en comparación con elin_array
que tiene un rendimiento O (n).Solo una nota adicional: si el servidor se ejecuta en un puerto que no sea 80 (como podría ser común en una máquina de desarrollo / intranet), entonces
HTTP_HOST
contiene el puerto, mientrasSERVER_NAME
que no lo hace.(Al menos eso es lo que he notado en los hosts virtuales basados en el puerto de Apache)
Como Mike ha señalado a continuación,
HTTP_HOST
hace no contener:443
cuando se ejecuta en HTTPS (a no ser que se está ejecutando en un puerto no estándar, que no he probado).fuente
HTTP_HOST
no es exactamente elHost:
parámetro que proporcionó el usuario. Simplemente se basa en eso.Utilizar cualquiera. Ambas son igualmente (in) seguras, ya que en muchos casos SERVER_NAME se completa de HTTP_HOST de todos modos. Normalmente elijo 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, particularmente si podrían tener tokens de inicio de sesión en .org que perderían si se los enviara a El otro dominio.
De cualquier manera, solo necesita asegurarse de que su aplicación web solo responderá por dominios conocidos. Esto se puede hacer (a) con una verificación del lado de la aplicación como Gumbo's, o (b) utilizando un host virtual en el (los) nombre (s) de dominio que desea que no responde a las solicitudes que dan un encabezado de Host desconocido.
La razón de esto es que si permite que se acceda a su sitio con cualquier nombre antiguo, se expone a ataques de reenlace de 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, luego el nombre de host se mueve a la IP del atacante, tomando sus cookies / autenticación 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 principal).
No. Bueno, no debe usar nada en ningún atributo sin escapar
htmlspecialchars($string, ENT_QUOTES)
, por lo que no hay nada especial sobre las variables del servidor allí.fuente
attacker.com
como la mejor fuente primaria para la IP de su servidor"? Eso no parece significar nada para los motores de búsqueda, ¿qué va a hacer eso?http://example.com/
,http://www.example.com/
yhttp://93.184.216.34/
los combinaría en un solo sitio, elegiría las direcciones más populares y solo devolvería enlaces a ese versión. Si pudiera apuntarevil-example.com
a la misma dirección y hacer que Google vea brevemente que, como la dirección más popular, podría robar el jugo del sitio. No sé cuán práctico es esto hoy, pero he visto a atacantes rusos de granjas de enlaces intentar hacerlo en el pasado.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 ):
Anticuado:
Esta es mi traducción al PHP desnudo de un método utilizado en el marco de Symfony que intenta obtener el nombre de host de todas las formas posibles en orden de mejores prácticas:
fuente
if ($host = $_SERVER['HTTP_X_FORWARDED_HOST'])
ox = a == 1 ? True : False
. La primera vez que lo vi, mi cerebro estaba buscando una instanciación de $ host y una respuesta para "¿por qué solo hay un" = "signo?". Estoy empezando a no gustarme los lenguajes de programación de mecanografía débil. Todo está escrito de manera diferente. No ahorras tiempo y no eres especial. No escribo código de esta manera, porque después de que pase el tiempo, soy yo quien debe depurarlo. ¡Parece realmente desordenado para un cerebro cansado! Sé que mi inglés es inglés, pero al menos lo intento.Sí, es seguro de 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:La ventaja de
$_SERVER['HTTP_HOST']
es que su comportamiento está más bien definido que$_SERVER['SERVER_NAME']
. Contraste ➫➫ :con:
El uso de una interfaz mejor definida
$_SERVER['HTTP_HOST']
significa que más SAPI lo implementarán utilizando un comportamiento confiable y bien definido. (A diferencia del otro .) Sin embargo, todavía depende totalmente de SAPI ➫➫ :Para comprender cómo recuperar correctamente el nombre de host, primero debe comprender que un servidor que contiene solo código no tiene medios para conocer (requisito previo para verificar) su propio nombre en la red. Necesita interactuar con un componente que le proporcione 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:
solicitud del cliente / atacanteetc.
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 ➫➫ :
fuente
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 general es no confiar nunca en los valores del usuario, por lo que
$_SERVER['SERVER_NAME']
es la mejor opción.Como señaló Gumbo, Apache construirá SERVER_NAME a partir de valores proporcionados por el usuario si no establece
UseCanonicalName On
.Editar: Habiendo dicho todo eso, si el sitio usa un host virtual basado en nombre, el encabezado HTTP Host es la única forma de llegar a sitios que no son el sitio predeterminado.
fuente
Host:
valor de HTTP a menos que ya lo haya verificado , ya sea manualmente o mediante la configuración de su SAPI.No estoy seguro y realmente no confío
$_SERVER['HTTP_HOST']
porque depende del encabezado del cliente. De otra manera, si un dominio solicitado por el cliente no es mío, no ingresarán a mi sitio porque los protocolos DNS y TCP / IP lo dirigen 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 el
SetEnv MyHost domain.com
archivo .htaccess en la raíz y agregue este código en Common.phpIncluyo este archivo Common.php en cada página php. Esta página hace todo lo necesario para cada solicitud
session_start()
, como modificar la cookie de sesión y rechazar si el método de publicación proviene de un dominio diferente.fuente
Host:
valor fradulento directamente a la IP de su servidor.XSS
siempre estará allí, incluso si usa$_SERVER['HTTP_HOST']
,$_SERVER['SERVER_NAME']
O$_SERVER['PHP_SELF']
fuente
Primero quiero agradecerles por todas las buenas respuestas y explicaciones. Este es el método que creé basado en toda su respuesta para obtener la URL base. Solo lo uso en situaciones muy raras. Por lo tanto, NO hay un gran enfoque en los problemas de seguridad, como los ataques XSS. Quizás alguien lo necesite.
fuente