Evitar ataques XSS con PHP Input Filter

Hoy una lección de seguridad en programación web: Evitar que a vuestra página le hagan un ataque por XSS (Cross Site Scripting). Si no sabéis lo que es el Cross Site Scripting… os lo explica mejor la wikipedia y así me centro en el tema (una vez le hice un ataque de estos a la página de un grupúsculo neonazi que redirigía a un vídeo del desfile del orgullo gay en Youtube)

Bueno, hay frameworks como Symphony o CakePHP que ya se encargar de implementar este tipo de seguridad, al igual que también lo hacen ciertos gestores de contenidos. Pero si se da el caso de que no estás usando ninguno, estás haciendo PHP «a pelo», lo mejor será que recurramos a la clase PHP Input Filter. Dicha clase permite filtrar código malicioso ingresado en los formularios para prevenir ataques XSS de manera sencilla, pero tiene la cualidad de no limpiar determinadas etiquetas o atributos si queremos.

Para utilizar esta clase, la descargaremos desde el enlace anterior e incluiremos class.inputfilter.php al inicio de nuestro códgi. Luego crearemos una instancia de la clase InputFilter, entonces podremos filtrar los datos con el método process:

    require_once("class.inputfilter.php");
    $filter = new InputFilter();
    $variable = $filter->process($_POST['variable']);

Esto nos permitiría limpiar de etiquetas la variable enviada por $_POST llamada variable. ¿Y si queremos limpiar todos los campos enviados por el método post? Pues basta con pasarle todo el array:

$_POST = $filter->process($_POST);

Y con eso tendríamos el array $_POST limpio de etiquetas y securizado.

Pero ¿y si queremos permitir ciertas etiquetas? Imaginemos que desde un input text metemos texto formateado, y nos interesa que sí puedan subir saltos de línea, texto en negrita o cursiva. Pues muy sencillo también, ya que basta con pasar en la creación del objeto InputFilter un array con las etiquetas que queremos conservar como parámetro:

    $filter = new InputFilter(array('em', 'i', 'br', 'b', 'strong'));
    $_POST = $filter->process($_POST);

Y esto se puede llevar más allá, porque también podemos decir que se permitan ciertos atributos de ciertas etiquetas. Por ejemplo, imaginemos que queremos permitir que inserten enlaces junto a su href y a su id, pero ningún atributo más:

    $filter = new InputFilter(array('a'), array('href', 'id'));
    $enlace = $filter->process($_POST['enlace']);

Tras el array de etiquetas pasamos otro array de atributos, simplemente.

Con estos sencillos consejos lograrás que tus formularios sean más seguros en PHP.

8 comentarios en “Evitar ataques XSS con PHP Input Filter

  1. Pedro

    estoy utilizando PHP 5.3.13 al ocupar esta clase, utilizando array de tag, da el siguiente error: -> Deprecated: Function eregi() is deprecated in C:\wamp\www\php_poo_cc\video29\class\class.inputfilter.php on line 203

    1. Cierto, eregi() es la función usada para comparar expresiones regulares por inputfilter. La solución es modificar la librería inputfilter.php cambiando el eregi() de la línea 203 por preg_match(). No lo he probado, que no sé qué c*jones pasa con la web de phpclasses que ahora mismo no me deja conectar para descargarlo y probar. La idea es esa, te está marcando el error en la línea 203. Busca ahí la función eregi() y prueba a sustituirla por preg_match() usando los mismos parámetros. Ojo, preg_match() requiere la extensión PCRE, puedes informarte sobre ella en http://www.php.net/manual/es/book.pcre.php

      1. Pedro

        al ejecutar este codigo:
        <?php
        require_once 'class/class.inputfilter.php';
        $limpia = new InputFilter(array('a','hr','div'),array('href','target','id','aling'));

        $vinculo = 'BuscadorPrueba’;
        $vinculo = $limpia->process($vinculo);
        echo $vinculo;
        ?>
        daba error en la linea 203
        la función eregi ya no corre en php 5.3 en adelante
        if ((!eregi(«^[a-z]*$»,$attrSubSet[0])) || (($this->xssAuto) && ((in_array(strtolower($attrSubSet[0]), $this->attrBlacklist)) || (substr($attrSubSet[0], 0, 2) == ‘on’))))
        lo reemplace por lo siguiente y corre segun los parámetros indicado en el ejemplo indicado.
        if ((!preg_match(«#^[a-z]*$#i»,$attrSubSet[0])) || (($this->xssAuto) && ((in_array(strtolower($attrSubSet[0]), $this->attrBlacklist)) || (substr($attrSubSet[0], 0, 2) == ‘on’))))
        gracias

      2. Gracias por pegar tu ejemplo aquí. He intentado contactar con los desarrolladores para comentarles esta cuestión, para que lo actualicen, pero no he recibido respuesta.

  2. Pingback: Evitar inyecciones SQL con PHP | Kronus Team

  3. enrique perez

    hola,
    tengo el siguiente problema :
    estoy utilizando la version de PHP 7.1.1 y me sale el siguente error:
    preg_replace(): The /e modifier is no longer supported, use preg_replace_callback()
    cuando lo remplazo me dice que necesita un sgundo parametro.

Deja un comentario

Este sitio utiliza Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.