Seguridad: Consejos para evitar el Cross-Site Scripting en PHP

Posted by victor on April 25th, 2013
php-logoDejo algunos consejos que leí el otro día en una entrada publicada en el blog de Pádraic Brady titulada "20 Point List For Preventing Cross-Site Scripting In PHP" Consejos que no conviene olvidar por mucho framework que usemos. Algunos de ellos son propios de PHP y otros se pueden aplicar a cualquier otro lenguaje. Como siempre, el sentido común es muy importante.
  • Nunca muestres directamente el contenido obtenido de sitios no seguros sin realizar previamente un escapado de los datos.
  • Siempre validar los datos de entrada.
  • Cualquier dato que no esté de forma explícita en el código, es considerado como dato de origen no seguro.
  • La función htmlentities(), que convierte caracteres a su equivalente en entidades HTML, también es válida para datos XML. En caso de serializar XMLs, además usar htmlspecialchars() que se encarga de escapar caracteres con significado especial como >,<, & o las comillas.
  • Siempre usar los flags ENT_QUOTES, ENT_SUBSTITUT en la función htmlspecialchars(). La primera opción permite convertir comillas simples y dobles. La segunda evita devolver un string vacío en las secuencias inválidas de caracteres. También es muy recomendable validar la codificación de la cadena de entrada. Desde PHP >=5.4 la codificación por defecto es UTF-8.
  • No usar htmlspecialchars() como único medio para escapar recursos como Javascript, CSS o partes de una URL.
  • No usar json_encode() para escapar string con Javascript.
  • Usa la función rawurlencode() para escapar los string que se inserten en una URL. Esta función los acomoda para que cumplan con la sintaxis descrita en el RFC 3986. Después, escapa la URL completa con htmlspecialchars().
  • No pasar datos escapados de sitios no seguros, por ejemplo, string que serán interpretados como Javascript, al contexto de ejecución de Javascript: setAttribute(“onclick”, “no-hagas-esto”).
  • Valida siempre las URLs construidas en sitios no seguros.
  • Nunca validar URLs usando filter_var(). No funcionan y permiten pasar el filtro a URLs con código Javascript.
  • No mezclar recursos http y https en una misma página.
  • Todo el código HTML que provenga de sitios no seguros se debe limpiar con HTMLPurifier antes de mostrarlo.
  • También se puede usar HTMLPurifier para otros lenguajes como BBCode o Markdown.
  • Intenta evitar el uso de CSS y Javascript en línea.
  • Utiliza el Content-Type adecuado al contenido que se transmite.
  • Las cookies que solo usa nuestro servidor hay que marcarlas como HttpOnly.

HTMLPurifier

Esta librería es un gran aliado para la seguridad que nos permite analizar una entrada HTML, BBCode o Markdown y eliminar aquellas partes que contengan código malicioso. Además, nos asegura que el HTML de entrada cumple con el estándar declarado en el doctype. Instalarla es sencillo (Requiere PHP 5 y los test se han realizado para versiones >= 5.0.5) Puedes hacerlo de varias formas
  • Descargar la librería.
  • Usar Pear:
    pear channel-discover htmlpurifier.org
    pear install hp/HTMLPurifier
  • Clon Git: git clone git://repo.or.cz/htmlpurifier.git
Usarla es igualmente sencillo:
require_once '/path/to/HTMLPurifier.auto.php';

$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($codigo_html_no_seguro);
Para usuarios de Symfony2 existe un bundle desarrollado por @jmikola que incluye filtros para Twig:
{# Filters text's value through the "default" HTMLPurifier service #}
{{ text|purify }}

{# Filters text's value through the "custom" HTMLPurifier service #}
{{ text|purify('custom') }}
  Twitter: Pádraic Brady. Reddit: Comentarios del artículo.

Comments

comments powered by Disqus