Laboratorio: no permitir que accedan directamente a las urls empleadas en Ajax
16:20 H (CET)| Temas: AJAX · Laboratorio · PHP
Cuando usamos Ajax en nuestras aplicaciones solemos usar un script específico que devuelva los datos preparados para que el cliente los interprete y los muestre.
En algunas ocasiones no suele ser de nuestro agrado que usuarios accedan directamente a las URLs empleadas para Ajax.
Para evitar esta situación se puede usar un script sencillo. Se tomará en cuenta el valor de la variable de entorno HTTP_REFERER, la cual nos devuelve desde qué página se accede a nuestro script.
$ref = getenv('HTTP_REFERER');
Si el contenido de esta variable es false entonces es que se ha accedido directamente desde el navegador, si no, es que se accede desde una página, también habrá que comprobar que la página es la que nosotros queremos.
<?php
$ref = getenv('HTTP_REFERER');
if (!$ref || $ref != '[nuestra url]') {
?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"xhtml1-transitional.dtd">
<html>
<head>
<title>Sentido Web - Redireccionamiento Ajax</title>
</head>
<body>
<h1>Sentido Web - Redireccionamiento Ajax</h1>
<p><?php echo "Hola, son las ".date("H:i:s"); ?></p>
</body>
</html>
<?php
} else {
echo "Hola, son las ".date("H:i:s");
}
?>
En este caso mostraremos una página cuando no haya referer o no sea el que nosotros esperamos. También se podría hacer para que el referer estuviera en el servidor, pero eso lo dejo para que lo haga el que lo necesita.
Una funcionalidad parecida se podría usar por temas de accesibilidad, dependiendo de un parámetro que indique si se trata de una llamada Ajax o no, se devuelva la información para el script del cliente o se muestre la información en una página.
<a href="url-ajax.php" onclick="ajax('url-ajax.php?ajax=1')">Enlace</a>
En el caso de haber problemas de accesibilidad, el enlace accede a la página con la información. En caso contrario, ejecuta la funciona ajax(), indicándole que se trata de una llamada Ajax para que nos devuelva la información formateada, ya sea en XML o JSON o como queramos.
Relacionados
Feedback off | Del.icio.us
3. Luis ~ Jueves, 29 Mar 2007 | 00:14H:
Hola Alex.
No te entiendo muy bien, si no hay referer, el script te muestra el resultado dentro de un archivo HTML, que es lo que queremos.
Quizás te haya entendido mal, de todas formas lo de los bookmarks es algo en lo que no había pensado, ¿hace la misma función que si pongo la URL en la barra de direcciones? porque si es así, esa posibilidad si la he tenido en cuenta.
Saludos y gracias por el comentario
4. Ironic ~ Jueves, 29 Mar 2007 | 02:51H:
El referer es algo facilmente manipulable.
Se puede crear una peticion html que falsee el html y asi pasan el script de proteccion.
Lo quepodrias hacer,que no se si es falseable, es validar que la ip de la persona que realiza la peticion sea la misma que la de tu servidor. (supongo que tendras ip fija).
Eso me parece mas seguro que validar por referer.
5. Luis ~ Jueves, 29 Mar 2007 | 08:59H:
La petición Ajax la hace el navegador (cliente), nunca puede tener la IP del servidor, si estoy haciendo pruebas en el servidor si funcionaría, pero en el resto de los casos no.
No entiendo lo de falsear el html. Supongo que si se podría modificar el referer modificando la cabecera HTTP (creo que se hace así, pero no estoy seguro), pero sería mucho lío para conseguir algo que no es crítico. Estamos hablando de mostrar la información dentro de una página HTML o en formato datos para un script Ajax, para evitar que la gente acceda a nuestros datos de esa forma, pero realmente, esta medida es algo más estético que de seguridad, en cuestiones de seguridad yo no recomendaría este método.
Saludos
6. Kent Mentolado ~ Jueves, 29 Mar 2007 | 10:06H:
Efectivamente, como medida de seguridad es contraproducente. Utilizar el método del Referrer presenta los siguientes problemas:
1) Muy facilmente falseable. No me extrañaria que hubiera unas cuentas extensiones de FireFox que te permitan falsear el Referrer a tiro de click. En ultimo caso se puede modificar la peticion HTTP.
2) Si tienes varias páginas que acceden a ese AJAX, cambias de dominio o cambias la nomenclatura de tus páginas, tienes que mantener todos esos valores en la comprobación del Referrer.
3) No todos los navegadores tienen porqué enviar el Referrer.
Es interesante como securizar las url llamadas por AJAX para que no puedan ser llamadas directamente. La única opcion dificilmente falseable que se me ocurre es utilizar "ventanas temporales": es decir, solo sirvo el AJAX si esa misma IP con ese mismo UserAgent ha solicitado la página "padre" en los ultimos X segundos. Aún así es un problema en caso de varios ordenadores en la misma conexión o navegación a través de Proxys.
Creo que se llegará a convertir en algo crítico, pues pronto empezarán a aparecer ataques basados en AJAX (por ejemplo, forzar los parámetros para que AJAX devuelva otra información distinta a la que hemos previsto cuando lo programamos).
7. Luis ~ Jueves, 29 Mar 2007 | 10:33H:
La intención de esta entrada no era sobre seguridad era más bien estética, porque aparte de que puede ser falseable el referer, los temas de seguridad no son tan fáciles de tratar. Ajax, en muchos casos, lo veo como un modo de obtener información, y si esa información la quiero mostrar, no hay problema porque un usuario acceda a ella, el tema es que no me gustaría que directamente se acceda a los datos.
Sobre lo de la "ventana temporal", le veo una pega, y se trata de por ejemplo GMail, abro GMail, se almacena mi ip y UserAgent, realizo peticiones Ajax, en tantos segundos... el problema es que la página de Ajax la puedo tener abierta 2 horas de forma continuada, por lo que lo de X segundos no me valdría en este caso.
Si realmente quiero ocultar las llamadas Ajax, ahora mismo no se me ocurre cómo podría hacerlo sin que otros puedan romper la seguridad. Todo sería ponerse a pensar como loco.
Saludos y gracias por el aporte.

