¡Hola! Me parece que andas usando un bloqueador de anuncios =( ¿Nos desbloqueas? ¿Por qué?
F13

Funcion 13

Entiende los ataques XSS y aprende a prevenirlos en PHP

No hace mucho estuvimos viendo los ataques CSRF, qué son y cómo prevenirlos. Hoy vamos a hablar de uno de los ataques más comunes en cualquier página web.

Los ataques XSS, Cross-site Scripting, son básicamente, inyecciones de código atacante que se hace posible gracias a la validación incorrecta de los datos introducidos por un usuario que, por lo general, es introducido en una página con un formulario o con algún enlace alterado.

Los ataques, por desgracia, ocurren porque los desarrolladores no se encargan de blindar el código. Es muy importante entender cómo funcionan estos ataques con scripts PHP para evitar posibles vulnerabilidades en vuestros scripts. En este artículo descubrirás más sobre este tipo de ataques y cómo prevenirlos.

¿Cómo funciona un ataque XSS?

Veamos el siguiente código:

<form action="post.php" method="post">  
  <input type="text" name="comentario" value=""> 
  <input type="submit" name="enviar" value="Enviar">
</form>  

Como ves, tenemos un formulario muy sencillo, para enviar un comentario de forma sencilla. Una vez que el formulario haya sido enviado, lo enviará al archivo post.php para procesarlo. Digamos que este archivo lo guarda en base de datos y luego lo pone en la página de la siguiente forma:

echo $_POST['comentario'];  

Sin ningún tipo de filtrado, ahí sin más. ¿Qué pasaría si alguien enviara un comentario de este tipo?

<script>alert('¡Hackeado!');</script>  

El código JavaScript sería evaluado y, efectivamente, sería ejecutado. Este código no es nada malicioso, aparte de ser molesto. Imagina si el JavaScript lo que hace es robar el contenido de una cookie y enviarla a cualquier sitio.

Los ataques XSS se diferencian entre ataques persistentes y no persistentes.

Ataque XSS persistente

Este tipo de ataque tiene lugar cuando el código ya pasó el código de validación y está almacenado en algún tipo de soporte, ya sea una base de datos o un fichero que requiera datos del usuario en algún momento. Cuando esa información sea presentada en la web, el código malicioso será ejecutado.

Veamos el siguiente ejemplo que usa un fichero como soporte de datos. Ten en cuenta que es muy rudimentario pero únicamente pretende ilustrar lo que ocurre.

// Guardamos el comentario en un fichero 
file_put_contents('comentarios.txt', $_POST['comentario'], FILE_APPEND);  

Como puedes ver, cuando el usuario envía el comentario, queda guardado en un fichero de datos. Más tarde, al acceder a la página en cuestión, exponemos el contenido de comentarios.txt para mostrar los comentarios a los visitantes:

echo file_get_contents('comentarios.txt');  

En cuanto los datos son expuestos (una serie de comentarios), en caso de haber código malicioso almacenado, este será mostrado (y ejecutado).

XSS no persistente

Al contrario que el caso anterior, el código malicioso no queda almacenado en el servidor sino que se pasa directamente a la víctima. Es la forma más habitual de XSS. El ataque se lanza desde una fuente externa como un correo aparentemente inofensivo, un mensaje de chat u otro sitio web.

Veamos un sencillo ejemplo:

echo "Mostrando resultados de: ".$_GET['busqueda'];  
// Este código que iría aquí abajo mostraría una serie de resultados

Este es un típico ejemplo de página totalmente insegura en la que una cadena de búsqueda es mostrada al usuario. El problema es que la variable $_GET['busqueda'] no es validada ni escapada por lo que un atacante podría enviar el siguiente enlace a la víctima.

http://www.pagina-victima.com/buscar.php?busqueda=<script>alert('¡Hackeado!');</script>

Sin validación alguna, la página mostrará:

Mostrando resultados de:<script>alert('¡Hackeado!');</script>

Evitando ataques XSS

Por suerte para todos, prevenir este tipo de ataques es realmente sencillo. Una vez que aprendas cómo hacerlo, es algo que siempre deberías tener presente a la hora de hacer cualquier aplicación web.

La primera regla, que realmente se aplica en todo lo relacionado con la seguridad, es la de no confiar nunca en datos que obtengas de los usuarios o de cualquier fuente de datos externa. Lo podría poner más grande, o en un color más molesto, pero no lo podría decir más claro.

Esta regla es la única que tenemos que seguir para prevenir los ataques XSS. Para tener unas buenas medidas de seguridad que eviten ataques XSS, tendremos que llevar a cabo la validación de datos, el saneamiento y escapar lo que vayamos a mostrar.

En este artículo nos centraremos en los dos últimos, porque la validación no es fundamental en este caso.

Saneando los datos

El saneamiento de datos se centra en manipular los datos para asegurarnos de que nos quedamos con lo que nos interesa. Por ejemplo, si quieres guardar el nombre de un usuario, no te interesa para nada el HTML que pudiera contener.

Veamos cómo podemos eliminarlo:

// Saneando el HTML 
$comentario = strip_tags($_POST['comentario']);

Escapando los datos

Para proteger los datos y mostrarlos tal y como los introdujo el usuario (pero evitando los problemas), deberías escapar los datos al presentarlos al usuario. Esto evita que el navegador lo ejecute y evalúe este código.

Por suerte, tenemos una función muy sencilla para esto:

// Vamos a escapar la variable antes de mostrarla 
echo "Mostrando resultados de: ".htmlspecialchars($_GET['busqueda']);  

Todo a la vez

Para comprender mejor todo el proceso, echemos un último vistazo a nuestro rudimentario sistema de comentarios y vamos a modificarlo para asegurarnos de que es 100% seguro. El punto vulnerable de nuestro archivo, comentarios.txt es sin duda el formulario que recibe datos a través de la variable $_POST['comentario']. Para hacerlo más seguro, tendremos que sanear y escapar los datos de esta variable.

$comentario = trim($_POST["comentario"]); 

if (empty($comentario)) {  
  exit("¡Debes introducir un comentario!"); 
}
// Sanear comentario 
$comentario = strip_tags($comentario); 

// Ahora podemos guardarlos 
file_put_contents("comentarios.txt", $comentario, FILE_APPEND); 

// Escapamos los comentarios antes de mostrarlos 
$comentarios = file_get_contents("comentarios.txt"); 

echo htmlspecialchars($comentarios);  

Lo primero que hacemos es asegurarnos de que hay un comentario eliminando además todos los espacios en blanco que haya al inicio y al final del comentario.

Luego saneamos el comentario eliminando las etiquetas HTML que pudiera tener. Finalmente guardamos los comentarios y ya estarán preparados para ser mostrados al usuario.

Resumen

Ahora deberías estar preparado para poder proteger tu código un poco más. Ten en cuenta que no hay ninguna solución que evite al 100% los ataques.

Recuerda que nunca debes confiar en los datos que provengan del usuario, ni de fuentes externas. Siguiendo estos sencillos pasos deberías ser capaz de hacer tu aplicación más segura.

Si el artículo te pareció interesante, útil o incluso equivocado, por favor considera el dejar un comentario. ¡Lo apreciaré mucho!

Programador Front-end en First + Third y Potato. Trabajando con JavaScript y HTML5 desde el corazón de Sevilla.

Comentarios ¡Únete a la conversación!