Determinando Referer en PHP

102

¿Cuál es la forma más confiable y segura de determinar qué página envió o llamó (a través de AJAX) la página actual? No quiero usar el $_SERVER['HTTP_REFERER'], debido a la (falta de) confiabilidad, y necesito que la página a la que se llama provenga solo de solicitudes que se originan en mi sitio.

Editar: Estoy buscando verificar que se esté llamando a un script que preforma una serie de acciones desde una página de mi sitio web.

UnkwnTech
fuente
5
¿Por qué dice que $ _SERVER ['HTTP_REFERER'] no es confiable?
Milan Babuškov
9
La implementación de PHP es confiable. El problema es que ningún navegador envía esto, e incluso puedes modificarlo si quieres. Por lo tanto, no es confiable que sea correcto por parte del cliente.
Biri
2
Una forma posible es poner una clave única (por ejemplo, un GUID) en un campo de su página y enviarla en la siguiente solicitud.
PhiLho
Descubra la dirección IP del servidor y utilice $_SERVER[REMOTE_ADDR].

Respuestas:

93

El REFERER es enviado por el navegador del cliente como parte del protocolo HTTP y, por lo tanto, no es confiable. Puede que no esté allí, puede que esté falsificado, simplemente no puedes confiar en él si es por razones de seguridad.

Si desea verificar si una solicitud proviene de su sitio, no puede, pero puede verificar que el usuario haya estado en su sitio y / o esté autenticado. Las cookies se envían en solicitudes AJAX para que pueda confiar en ellas.

Seldaek
fuente
5
Si desea utilizar este método, también debe verificar la referencia para evitar CSRF en.wikipedia.org/wiki/Cross-site_request_forgery
JD Isaacks
17
Idealmente, debería usar un token único por sesión por usuario (por solicitud si es paranoico) para prevenir ataques CSRF. Verificar la referencia es solo seguridad por ofuscación y no es una solución real.
Seldaek
3
@Seldaek no, verificar el referente no es 'seguridad por ofuscación'. Un atacante que intenta realizar un ataque CSRF no puede controlar el árbitro enviado por el navegador de la víctima, lo que la comprobación se hace a proteger contra CSRF. Sin embargo, mantendré tu conclusión de que deberías usar un token CSRF en su lugar, ya que el enfoque de verificación de referencia tiene desventajas, como dejarte vulnerable si tienes una redirección abierta en tu sitio y romper para los agentes de usuario que eliminan al referenciador.
Mark Amery
@MarkAmery, todo depende de lo que intente defenderse, por supuesto, pero el uso de encabezados http específicos del cliente no es, en general, un modelo de seguridad muy sólido.
Seldaek
23

Lo que mejor he encontrado es un token CSRF y lo guardo en la sesión para los enlaces donde necesita verificar la referencia.

Entonces, si está generando una devolución de llamada de FB, se vería así:

$token = uniqid(mt_rand(), TRUE);
$_SESSION['token'] = $token;
$url = "http://example.com/index.php?token={$token}";

Entonces el index.php se verá así:

if(empty($_GET['token']) || $_GET['token'] !== $_SESSION['token'])
{
    show_404();
} 

//Continue with the rest of code

Sé de sitios seguros que hacen el equivalente a esto para todas sus páginas seguras.

We0
fuente
1
Aquí hay un enlace para obtener más información sobre los tokens CSRF: en.wikipedia.org/wiki/Cross-site_request_forgery
We0
7
¿Estás seguro de que lo es $_GET['token'] == $_SESSION['token']y no $_GET['token'] !== $_SESSION['token']?
Timo Huovinen
17

Usando $ _SERVER ['HTTP_REFERER']

La dirección de la página (si la hubiera) que remitió al agente de usuario a la página actual. Esto lo establece el agente de usuario. No todos los agentes de usuario establecerán esto y algunos brindan la capacidad de modificar HTTP_REFERER como una función. En resumen, realmente no se puede confiar en él.

if (!empty($_SERVER['HTTP_REFERER'])) {
    header("Location: " . $_SERVER['HTTP_REFERER']);
} else {
    header("Location: index.php");
}
exit;
Lawrence Cherone
fuente
0

No existe una forma fiable de comprobarlo. Realmente está en manos del cliente para decirle de dónde vino. Puede imaginar usar cookies o información de sesiones colocada solo en algunas páginas de su sitio web, pero al hacerlo, su experiencia de usuario con marcadores se rompería.

artilugio
fuente
0

Solo nos queda una opción después de leer todos los problemas de referencias falsas: es decir, la página que deseamos rastrear como referencia debe mantenerse en sesión, y como se llama ajax luego verificar en la sesión si tiene un valor de página de referencia y realizar la acción de otra manera no acción.

Mientras que, por otro lado, cuando solicita cualquier página diferente, haga que el valor de la sesión de referencia sea nulo.

Recuerde que la variable de sesión se establece solo en la solicitud de la página deseada.

Justnajm
fuente