Prevenir ataques XSS con PHP

Una ataque XSS (Cross Site Scripting) consiste en que el atacante ingresa código HTML o javascript en los formularios y si estos no esta filtrados correctamente mostrarán este código en nuestra página alterando el contenido original. Por ejemplo en un formulario de contacto un usuario podría colocar el siguiente código:

<script>window.location = "http://www.google.com";</script>

Si nuestro formulario no valida correctamente estos datos ingresados, entonces al momento de mostrar este comentario en nuestra web automáticamente se hará un redirección a la ruta que defina el atacante. Basado en esto podríamos proponer un regla básica para cualquier desarrollo:

Toda información ingresada por el usuario siempre debe ser verificada y limpiada antes de utilizarla

Prevenir XSS con PHP (Básico)

Lo primero para prevenir estos ataques es limpiar cualquier etiqueta html ingresada por el usuario, para ello podemos utilizar la función strip_tags, la cual elimina etiquetas html. Si aplicamos esta función al texto ingresado en el ejemplo anterior tendríamos:

echo strip_tags('');
// resultado: window.location = "http://www.google.com";

Esto es una forma básica de prevenir un ataque XSS, pero existen versiones mas elaboradas de códigos de ataque que pueden no ser limpiadas por esta función. Otro problema de esta solución es que limpia todas las etiquetas html, pero en algunas ocasiones existe la necesidad de permitir algunas etiquetas (Por ejemplo: p, strong, em) para lo cual necesitamos una solución mas elaborada.

Prevenir XSS con PHP Input Filter

PHP Input Filter, es una clase escrita en PHP que permite filtrar código malicioso ingresado en los formularios para prevenir ataques XSS de manera sencilla, tiene la cualidad de no limpiar determinadas etiquetas o atributos.

Para utilizar esta clase, descargamos los archivos desde el web oficial e incluimos el archivo class.inputfilter.php al inicio de nuestro PHP. Luego se debe crear una instancia de la clase InputFilter, entonces podemos filtrar los datos con el método process de la siguiente forma:

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

También se pueden filtrar todos los campos enviados por el formulario, por ejemplo si el formulario es enviado por el método POST, podríamos utilizar el siguiente código para filtrar todos los campos para luego utilizarlos sin problemas.

require_once("class.inputfilter.php");
$ifilter = new InputFilter();
$_POST = $ifilter->process($_POST);

Permitir etiquetas con PHP Input Filter

Para evitar que algunas etiquetas sean filtradas podemos pasarlas como un array como parámetro al momento de crear la instancia de la clase. Por ejemplo para permitir las etiquetas strong yem y tendríamos:

require_once("class.inputfilter.php");
$ifilter = new InputFilter(array('em', 'strong'));
$_POST = $ifilter->process($_POST);

Permitir atributos con PHP Input Filter

También existe la posibilidad de desear que algunos atributos sean permitidos en el ingreso de los datos por parte del usuario. Por ejemplo podríamos permitir que los visitantes puedan ingresar enlaces para lo cual tendríamos que permitir el atributo href que contiene la ruta de destino.

require_once("class.inputfilter.php");
$ifilter = new InputFilter(array('a'), array('href'));
$comentario = $ifilter->process($_POST['comentario']);

Mas Información

Comentarios Total 13 comentarios

Carluis Pérez
Publicado: 05/08/2010 5:04 pm

Buen Tema! la explicación «Prevenir XSS con PHP (Básico)» es la más utilizada para los Formularios como por ejemplo: Libros de Visitas,Formularios de Comentarios u otros tipos de formularios mal programados o demasiado simples,también se pueden utilizar otras funciones como por ejemplo:

function hackerDefense(){
// begin hacker defense
foreach ($_POST as $secvalue) {
if ((eregi(«]*script.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*object.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*iframe.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*applet.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*window.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*document.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*cookie.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*meta.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*style.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*alert.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*form.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*php.*\»?[^>]*>», $secvalue)) ||
(eregi(«]*]*>», $secvalue)) ||
(eregi(«]*img.*\»?[^>]*>», $secvalue))) {
header(‘location:’.$site.’index.php’);
die ();
}

hackerDefense();
$ejemplo = $_POST[‘textarea’];
}

Es cuestión de poner aprueba la programación.

David
Publicado: 06/08/2010 6:28 pm

Bueno pues se ve muy bien la clase pero creo que se podria hacer algo asi …

function Security($_Cadena) {
$_Cadena = htmlspecialchars(trim(addslashes(stripslashes(strip_tags($_Cadena)))));
$_Cadena = str_replace(chr(160),'',$_Cadena);
return mysql_real_escape_string($_Cadena);
}

jejejej espero que les pueda servir =)

Carluis Pérez
Publicado: 10/08/2010 4:12 pm

Aca otra función para prevenir ataques xss es:

function limpiar_tags($tags){
$tags = strip_tags($tags);
$tags = stripslashes($tags);
$tags = htmlentities($tags);
return $tags;
}

limpiar_tags($variable);

Es simple pero muy efectiva…


[…] Librería PHP para evitar SQL injection y XSS, donde se nos habla de Genius Open Source Libraries y Prevenir ataques XSS con PHP donde se comenta sobre el PHP Input […]

Sabrina
Publicado: 02/11/2010 10:27 am

Hola, según mi hosting estoy sufriendo ataques XSS en mi web.
Me estan llegando mails como si me los estuviera enviando yo con publicidades SPAM.
Mi consulta es, donde tengo que poner el código para que limpie los tags??
por ejemplo el código que puso Carluis Pérez, dónde lo pongo???… en el php de la función enviar comentario del formulario??
Por favor que alguien me responda proque no se cómo solucionarlo.
Gracias.
Sabrina

unijimpe
Publicado: 02/11/2010 10:31 pm

Sabrina, una ataque XSS consiste en poner código HTML en los formularios de forma que alteren tu web. Respecto a lo que mencionas están enviando SPAM a tu email, esto ocurre cuando uno publica direcciones de email en la pagina, hay robots que lees y extraen las direcciones de email para luego enviar correo masivo.

Otra forma para hacer SPAM es utilizar los formularios, si estos no tienen validación o un filtro con CAPTCHA los SPAMMER hacen envío masivo de correos utilizando estos formularios.

servidor
Publicado: 23/09/2011 4:25 pm

MUy buen consejos ahora lo aplico a mi web.
Saludos.

Gonzac
Publicado: 09/12/2011 8:11 am

Hola, estube buscando este tipo de informacion, nunca está de mas aprender algo mas. Debo felicitarte!, muy bien explicado.
Es incrible la cantidad de paginas diseñadas por gente que sabe, y dejan de lado estas simples cosas.

Estube escribiendo sobre «xss en uri», pero sobre otros tipo de variables php.
Por si te interesa..
http://gonzac-studios.blogspot.com/2011/11/hack-ejecucion-de-codigo-en-uri.html

Saludos!

sharigan
Publicado: 13/01/2012 9:02 am

hola mi consulta es si esto tambiewn sirve para prevenir ese tipo de ataques es un htacces pongo el codigo siguiente

## Manejo de errores de Apache. Cuando se produzca uno de estos errores, redirigimos a una pagina especial desarrollada por nosotros.
ErrorDocument 401 http://www.lasombradehotmail.com/404error.html
ErrorDocument 403 http://www.lasombradehotmail.com/404error.html
ErrorDocument 404 http://www.lasombradehotmail.com/404error.html

RewriteEngine On
Options +FollowSymLinks

# Evitar escaneos y cualquier intento de manipulación malintencionada
# de la URL. Con esta regla es imposible lanzar ataques de inyección (SQL, XSS, etc)
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^(-|\.|’) [OR]
RewriteCond %{HTTP_USER_AGENT} ^(.*)(|%3C|%3E)(.*) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget)(.*) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(.*)(libwww-perl|libwwwperl|snoopy|curl|wget|winhttp|python|nikto|scan|clshttp|archiver|loader|email|harvest|fetch|extract|grab|miner|suck|reaper|leach)(.*) [NC,OR]

RewriteCond %{REQUEST_URI} ^(/,|/;|/|/’|/`|/%2C|/%3C|/%3E|/%27|/////) [NC,OR]
RewriteCond %{HTTP_REFERER} ^(.*)(%00|%08|%09|%0A|%0B|%0C|%0D|%0E|%0F|%2C||’|%3C|%3E|%26%23|%27|%60)(.*) [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)(%00|%08|%09|%0A|%0B|%0C|%0D|%0E|%0F|%2C|%3C|%3E|%27|%26%23|%60)(.*) [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)(‘|-||,|/|\\|\.a|\.c|\.t|\.d|\.p|\.i|\.e|\.j)(.*) [NC,OR]
RewriteCond %{HTTP_COOKIE} ^(.*)(|’|%3C|%3E|%27)(.*) [NC]
RewriteRule ^(.*)$ error.php [NC]

## Evitar que se liste el contenido de los directorios
Options All -Indexes

# Protegerse contra los ataques DOS limitando el tamaño de subida de archivos
LimitRequestBody 1024000

## Lo mismo que lo anterior
IndexIgnore *

## Denegar el acceso a robots dañinos, browsers offline, etc
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} ^Anarchie [OR]
RewriteCond %{HTTP_USER_AGENT} ^ASPSeek [OR]
RewriteCond %{HTTP_USER_AGENT} ^attach [OR]
RewriteCond %{HTTP_USER_AGENT} ^autoemailspider [OR]
RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
RewriteCond %{HTTP_USER_AGENT} ^Xenu [OR]
RewriteCond %{HTTP_USER_AGENT} ^Zeus.*Webster [OR]
RewriteCond %{HTTP_USER_AGENT} ^Zeus

##redireccionar a los robots a otra web
RewriteRule ^.*$ http://www.google.com [R,L]

no se si sirva pero lo pongo pero me gustaria saber mas respecto a eso si sirve bien gracias por los coemntario ando aplicando tu codigo en mi web a ver si me funciona graciassss

alert()
Publicado: 15/01/2012 12:36 am

alert()

Jessica
Publicado: 19/05/2012 12:13 pm

Geniales… Los voy a implementar.
Gracias a todos por la info!

fernando
Publicado: 05/10/2012 10:10 pm

Estos códigos pienso que no sirven asta que se imprimen en el contenido html osea si no imprimimos los comando Xss no se ejecutaran : seria simple que reemplazan » o < por sus abreviaturas en html

Oscar Bravo
Publicado: 19/07/2013 11:56 pm

Excelente aporte.. felicidades hacen un gran trabajo..
les dejo un link por si alguien quiere leer un poco mas al respecto.
http://quechuletas.blogspot.mx/2013/07/evitando-ataques-xss-con-php.html

 

Comentar

En este blog los comentarios están moderados, serán mostrados cuando el administrador los apruebe. Por favor, evita comentarios ofensivos u obscenos por que no serán aprobados.
Si deseas publicar código fuente debes hacerlo entre las etiquedas <code> y </code>, además debes reemplazar los carácteres < por &lt; y > por &gt;.

(Requerido)

(Requerido, no será publicado)

(Requerido)

(Tags aceptados: <a> <em> <strong> <code> <ul> <li>)