miércoles, 21 de mayo de 2008

Protección básica contra Cross-site scripting (XSS)

Los ataques Cross-site scripting (XSS) o de HTML injection pueden ser prevenidos de manera bastante simple tomando algunas medidas de seguridad básicas que debemos tener siempre presentes.

Este tipo de ataque consiste en incrustar código HTML en un sitio web con el objetivo de poder ejecutar código Javascript arbitraro o incluir código HTML con el fin de -por ejemplo- realizar ataques de phishing.

La preveción de este tipo de ataque se realiza filtrando la infomación que se ingresa y publica en nuestro sitio, por lo que tenemos dos puntos de control:
  • Filtrar datos ingresados
  • Escapar datos publicados en la WEB

Filtrar datos ingresados
La media de prevención más sencilla es impedir que los usuarios del sitio puedan publicar información, como por ejemplo cuando se hacen comentarios en un blog o en formularos de contacto.

En caso que el sitio deba permitir el ingreso de información, se debe definir si se aceptará código HTML. En caso que se opte por no aceptar código HTML será necesario filtrar todo el contenido recibido desde formularios para quitar eventuales tags HTML que ingrese el usuario. Esto se puede realizar con la siguiente función:
$comentario = strip_tags($comentario);
La función strip_tags() no realiza validación de que el código HTML esté bien formado, por lo que potencialmente se podría perder información -mal- ingresada por el usuario. Se puede realizar una validación más apropiada por medio de tidy.

En caso que sea necesario permitir el ingreso de código HTML, se deberán restringir los tags HTML que serán permitidos. Usualmente se permiten los tags de texto básico como <p>, <br>, <i>, <b>, <strong>, <em>, <blockquote> y tags de listas como <ul>, <ol> y <li>. Especialmente se debe evitar la inclusión de tags HTML que permitan la inclusión de contenidos externos como por ejemplo <script>, <frame>, <iframe>, <object> y <a>.

El filtrado de los tags HTML permitidos se puede realizar con el siguiente comando:
$comentario = strip_tags($comentario, "<p><br><strong><em>");
Sin embargo, nuevamente la función strip_tags() puede presentar problemas porque los tags admitidos podrían contener atributos peligrosos como onload y onmouseover. Por lo que se debería recurrir a una combinación de tidy y expresiones regulares.

Las tareas de filtrado se pueden enfrentar de dos maneras: Manteniendo una lista negra de tags y atributos no permitidos o manteniendo una lista blanca con los tags y atributos permitidos. En vista de evitar problemas de seguridad, es más recomendable mantener una lista blanca que contenga los elementos admitidos ya que es mucho menos grave restringir el ingreso de un dato inofensivo (falso positivo) que permitir el ingreso de un dato potencialmente peligroso.


Escapar datos ingresados
Como segunda medida de contención se puede agregar validación antes de publicar información en la WEB.

Se debe considerar que la información que ingresa a nuestras bases de datos (y archivos de caché) es introducida por diversos medios, como por ejemplo WebServices, migraciones de datos o SQL Injection, por lo tanto aunque se mantenga absoluta seguridad en nuestros formularios WEB, siempre existe la posibilidad de contar con datos peligrosos. Debido a esto, seimpre es recomendable filtrar la información que se publica en nuestro sitio.

En primer lugar debemos distinguir si la información que publicamos puede contener HTML o no.

En general la gran mayoría de la información que se publica en la web -como por ejemplo nombres, fechas, títulos- no contiene código HTML. En estos casos la información a imprimir en una página web debe ser escapada para reemplazar los caracteres especiales por sus entidades respectivas, esto se realiza con el siguiente comando:
echo htmlspecialchars($nombre);
Esta función tiene la ventaja que imprime correctamente textos como "Barnes & Noble" y "A < B < C" que en caso de no ser escapados no se visualizarían correctamente.

En el caso de publicar contenidos con HTML, se debe aplicar la misma función de filtrado que se utiliza al momento de ingresar datos.

Con estas simples medidas se aumenta en gran medida el nivel de seguridad ante ataques XSS.

1 comentario:

marcelo dijo...

Hola, una pregunta, en que lugar se pondrían esas líneas de código??
gracias