jueves, 31 de octubre de 2013

Algunos ejemplos y defensas contra el clickjacking

El clickjacking fue descubierto por Jeremiah Grossman y Robert Hansen en 2008. También se le conoce como UI redressing. El concepto es sencillo, y las técnicas para conseguirlo no son difíciles de implementar. Se podría decir que la técnica se basa en un fallo de diseño de HTML y por tanto toda web es "vulnerable" por defecto. Las soluciones hasta ahora son en realidad "parches" aplicados tanto al protocolo como a los navegadores, que han aparecido para intentar mitigar el problema.

El fin del clickjacking es conseguir que un usuario pulse en un enlace (y realice una acción) sin que lo sepa, o creyendo que lo hace en otro enlace con otro fin, con todas las consecuencias que eso puede acarrear. Puede ser un enlace de votación (que vote a alguien que no desea), seguir a alguien en Twitter, un "Me gusta" de Facebook... El atacante "disfraza" un enlace no deseado, volviéndolo atractivo para la víctima. Para conseguirlo, se basa en el juego de capas que se puede conseguir con HTML e "iframe". Iframe es una (anticuada en cierta forma) técnica para cargar una web dentro de otra. Clickjacking está basado normalmente en el iframe.
Para una explicación de cómo realizar este ataque, se debe entender el funcionamiento por capas intrínseco al HTML. Una web maliciosa (roja, en la figura) debe cargar una web legítima (gris) delante pero , de forma transparente (con opacidad cero). La web roja consistirá en un mensaje atractivo, en el que el usuario desee pinchar. La web legítima será la "víctima" en el sentido de que el usuario realmente pulsará sobre ella sin quererlo. Además, será víctima del ataque porque permite que se "abuse" de ella (veremos cómo evitarlo). Si se posiciona correctamente un enlace sobre otro, y se cuadran las capas, el efecto puede ser el del "secuestro" del clic del ratón.

Para preparar la página maliciosa, el atacante debe contar con dos componentes básicos:

  • Un iframe a cualquier otra página, que en este caso será la "víctima", o en rigor, la página que será finalmente pulsada, sin que lo sepa el usuario.
  • Este iframe debe servirse desde la página maliciosa aplicando un estilo concreto que permita que sea transparente y quede posicionada por delante, en el punto correcto. Por ejemplo

El "style" definirá el ataque.

  • opacity:0. Vuelve transparente al elemento. Su valor va de 1 (totalmente opaco) a 0, transparente e invisible.
  • position: El elemento se coloca en relación a su primera posición (no estática) elemento antecesor.
  • top:0px;left:0px;width:99%;height:95%;margin:0px;padding:0px. Estos parámetros permiten tomar todo el ancho de una página y que se acople a sus márgenes para que la cubra totalmente
  • z-index:1. Permite que se posicione por delante/encima de cualquier otro elemento. Si este número se incrementa (puede valer 100, por ejemplo), se posicionará delante de todo lo que tenga un z-index menor. Si el número es negativo, se posicionará por detrás.

El ataque completo, podría ser algo así:

Y cuando el usuario crea pulsar sobre un enlace muy atractivo o conveniente para él, en realidad puede que esté realizando una transferencia, por ejemplo.

Una ventaja de esta técnica que la diferencia del CRSF (cross site request forgery), es que con ella se sigue disponiendo del token válido en el caso de páginas que necesiten sesión, y si el usuario está presentado en la web "víctima", lo hará con el mismo token y como si realmente la acción se hubiera realizado desde la página original.

Pero se puede ir más allá. El problema inicial se definió en 2008 con este vídeo, en el que se presentaba un ejemplo en el que la víctima activaba inadvertidamente su cámara web al presionar botones en la propia página de Adobe.

 

Un ejemplo concreto

Imaginemos un sistema de votación muy sencillo, alojado en un dominio culaquiera, en la web vulnerable.php.

El atacante utiliza test.html, que carga mediante un iframe la página vulnerable.php de forma transparente con opacidad 0. La carga "por delante" de test.htm, pero al ser transparente, el usuario solo visualiza el contenido de test.html. En ella propone votar a otra web cualquiera, por ejemplo elladodelmal.com. Este es el reclamo. Pero el usuario que pulse sobre el botón, realmente estará votando a elevenpaths.com.

La última secuencia muestra una imagen de la aplicación test.htm con opacidad 1, lo que significa que se puede ver la aplicación vulnerable.php y test.php claramente una sobre la otra.

Evitar el ataque: en un sitio web

¿Qué puede hacer una página para que no sea utilizada como víctima del clickjacking? No puede hacer mucho más que evitar que se cargue ella misma dentro de un iframe. Así ningún atacante podrá ponerla "invisible" y sobre otra que el propio atacante ha creado. Una de las soluciones "antiguas" era la de evitar con JavaScript que una página no estuviera siempre en el "top".

Se debería incluir este código en cada página. Pero estas técnicas podían, a su vez, ser evitadas por el atacante.

Como solución más práctica, se ideó añadir al protocolo HTTP una cabecera llamada X-Frame-Options. Las páginas que envíen estas cabeceras al navegador, pretenden protegerse de aparecer en un iframe. Se propusieron varios métodos más o menos flexibles para intentar ayudar a las que legítimamente necesitaran incluirse dentro de un iframe. Sus valores son:

  • DENY, el navegador evita que la página sea renderizada si está contenida dentro de un iframe
  • SAMEORIGIN, la página solo puede ser mostrara en un frame que provenga del mismo origen que la propia página.
  • ALLOW-FROM uri, el navegador bloqueará la renderización sólo si el origen de nivel superior está en un contexto de navegación que es diferente al valor uri proporcionado en la directiva

Los usuarios deben confiar en que las páginas las envíen, y que su navegador las interprete correctamente. Esto último hace tiempo que ya lo implementan la mayoría. Por ejemplo, Chrome desde su versión 4.1.249.1042, Firefox desde 3.6.9, Internet Explorer desde la 8, Opera desde la 10.5...

Evitar el ataque: desde el cliente

Pero aunque la mayoría de páginas  ya se aprovechan de estas cabeceras, ¿qué pasa con las que no? El usuario debe protegerse. Ciertos antivirus detectan en el navegador comportamientos "extraños" de este tipo, y les han asignado firmas. Por ejemplo Avira, lo detecta como  HTML/Infected.WebPage.Gen2.
Otro método para protegerse es utilizar la funcionalidad "clearclick" del conocido plugin NoScript, que ofrecerá protección al usuario para FireFox.

Ejemplos de alertas sobre ClickJacking.
Fuente: http://blogs.computerworld.com/sites/default/themes/cw_blogs/cache/files/u91/noscript_clickjack.jpg 

Fuente: http://hackademix.net/2008/10/08/hello-clearclick-goodbye-clickjacking/

Os adjunto un video en el que muestro como mediante esta técnica un hacker sería capaz de desviar cientos de votos engañando a los usuarios habituales de una web que ha sido comprometida, creyendo estos estar cliqueando ‘Me gusta’ a una persona cuando realmente se esta votando a otra.

Clickjacking example 2

martes, 15 de octubre de 2013

Cómo aprovechar el autofill de Chrome para obtener información sensible

A finales de 2010, Google introdujo en Chrome autofill, una característica cómoda, pero que puede suponer un problema de seguridad para sus usuarios. Incluso después de que otros navegadores sufrieran problemas de seguridad relacionados con esta funcionalidad, y que la funcionalidad en sí haya sido cuestionada, sigue siendo posible robar la información almacenada del usuario que rellena un formulario sin que lo perciba.
En general, almacenar datos sensibles en el navegador no suele resultar una buena idea. Justo antes de que Chrome implementara el "Autofill", en verano de 2010, se descubrió cómo sacar todos los datos almacenados en Safari con fuerza bruta en JavaScript. El usuario rellenaba un campo pero el navegador se encargaba de rescatar todos los demás almacenados, probando todas las letras y dejando que el navegador hiciera el resto. La vulnerabilidad fue parcheada poco después. No hace tanto, en agosto de 2013, se criticó desde muchos frentes lo sencillo que era recuperar contraseñas almacenadas en Chrome, que podían observar en texto plano.
Con un sencillo método se puede conseguir que el usuario que escribe en un formulario, entregue esos datos a un tercero sin que sea consciente de ello.

¿Cómo funciona?

Autofill de Chrome permite almacenar la dirección postal (dividida en otros datos como nombre, apellidos, teléfono, código postal...) y la tarjeta de crédito (dividida en titular, número y fecha de caducidad). Los datos (excepto la tarjeta de crédito) se pueden sincronizar con la cuenta de Google. El menú de configuración y cómo acceder a él, se observa en la siguiente secuencia de imágenes.
http://code-disaster.blogspot.com
Imagen 1: Configuración del autofilling.
http://code-disaster.blogspot.com
Imagen 2: Configuración del autofilling (Direcciones).
http://code-disaster.blogspot.com
Imagen 3: Configuración del autofilling (Tarjetas de crédito)
Diferentes pantallas de configuración de "autofill" en Chrome
Para que un formulario aproveche el autofill, los inputs deben ser debidamente identificados para que Chrome sepa qué valores corresponden.
http://code-disaster.blogspot.com
Imagen 4: Atributos para el autofilling
Dispone de cierta heurística para intentar que casen los campos. Por ejemplo sabe que autocomplete="mail" debe ir autocompletado con el mismo contenido que cuando lleva de valor autocomplete="Work  email".

El "ataque"

Un atacante puede aprovechar esta característica del navegador para obtener información privada como puede ser los datos del domicilio o datos de la tarjeta bancaria. Planteamos un escenario en el que la víctima visite una página web por https especialmente modificada, introduzca los datos y el atacante se ayude del autofill que ofrece el navegador para obtener datos sensibles almacenados. Todo esto a pesar de las pequeñas trabas que introduce Chrome en su código para evitarlo.
Por ejemplo, como precaución, Chrome solo proporciona la tarjeta de crédito a páginas bajo https. Esto no es ningún problema para un atacante, pues es solo tiene que operar a través de una conexión SSL. Existen páginas fraudulentas que funcionan con certificados gratuitos.
El segundo paso es preparar el formulario y ocultar a los ojos de la víctima, los inputs que interesan al atacante. La primera aproximación pensaría en utilizar la etiqueta "hidden". Pero en el input el atributo type no puede llevar ese valor. Una segunda aproximación podría ser introducir el formulario dentro de un div con la propiedad visibility en "hidden"... pero Chrome evita que los inputs sean auto-rellenados cuando se cumplen estas condiciones. ¿Cómo conseguirlo entonces?
Una fórmula puede ser aprovechar la propiedad de scroll, subiendo la capa algunos píxeles para que no se observen el resto de inputs en los que se pretende recopilar la información. En este caso, el formulario "gancho" se vería:
http://code-disaster.blogspot.com
Imagen 5: PoC Autofilling
Pero, usando este "div", conseguimos que en su interior se oculten todos estos inputs y no se visualicen en el navegador:
div style ="overflow:hidden;height:25px;"
http://code-disaster.blogspot.com
Imagen 6: Campos ocultos en el formulario.
Chrome rellenará toda la información adicional sin que la vea el usuario. El atacante, recopilará la información y podrá disponer de muchos más datos de los que cree haber rellenado el usuario.
http://code-disaster.blogspot.com
Imagen 7: Recolección de los datos robados.
En resumen, aunque resulte cómodo (para sistemas usados por una misma persona solamente), debe evitarse el uso de la funcionalidad autofill, puesto que se ha demostrado que es posible ofrecer a cualquier página bajo https datos tan sensibles como el número de la tarjeta de crédito y su fecha de caducidad, sin que la víctima sea consciente.
Para evitar este problema (o potenciales en el futuro), por ahora el mejor remedio es simplemente no utilizar esta funcionalidad.
Ricardo Martín Rodríguez








martes, 1 de octubre de 2013

Inyecciones en inyecciones SQL

La entrada que traigo hoy, trata de como llevar un paso más haya las Union Based SQL Injection, por ejemplo si en algún caso nos vemos frente a una inyección SQL de este tipo, que no contiene datos aprovechables, como pueden ser subir una webshell u obtener las credenciales para acceder al login del gestor de la web que se esté auditando, etc. Se ha de tener en cuenta que un ataque como el Union Based SQL Injection se puede aprovechar de otras formas, y una de estas formas es la que hoy expondré.

Se trata ni más ni menos que aprovechar los campos imprimibles de la consulta SQL que por debajo está realizando la página web al cambiar los parámetros que se envían por la url. Aprovechándonos de dicha forma lograr inyectar además de la inyección SQL, código Javascript, HTML o por qué no realizar un SSI, de este modo podríamos desde ejecutar comandos en una Shell devuelta por el sistema que se muestra en la página (SSI), incluir un iframe para cargar un exploit (HTMLi), leer las cookies, suplantar un formulario como vimos en uno de los anteriores post de este blog Ataques XSS avanzados a aplicaciones webs: 3 Ejemplos; o cualquier otro que se nos ocurra, y es que de esta forma se lograría explotar otro tipo ataque que tal vez por estar bien protegida la web no se podría dar y con ello otra forma de ownear la web.

A continuación se puede ver un ejemplo de una inyección XSS sobre una inyección SQL ya que no se logró explotar de otra forma un XSS en lo demás de la web, siendo irrelevantes los datos obtenidos en la base de datos.

image
Imagen 1: XSS con SQLi en Google Chrome.

Otro punto a favor de realizar una inyección XSS de esta manera, es que se consigue Bypassear tanto los filtros Anti-XSS de navegadores como Google Chrome (Versión 29.0.1547.76 m) como los de IExplorer (10.0.9200.16660).

image
Imagen 2: XSS con SQLi en IExplorer.

Para realizar este ataque se debe primero preparar la inyección SQL de modo que quede así.
http://www.localhost.com/test.php?Op=2-1+union+select+1,2,3,4,5,6

image
Imagen 3: Búsqueda del campo imprimible.

Como se puede apreciar el campo imprimible es el que cae en el 5, entonces será cuestión de sustituirlo en este caso por la inyección XSS cifrada en Hexadecimal con cualquier conversor de Ascii a Hex.

Ascii: <script>alert("code-disaster.blogspot.com")</script>
Hex: 3c7363726970743e616c6572742822636f64652d64697361737465722e626c6f6773706f742e636f6d22293c2f7363726970743e

y por ultimo concatenar a la inyección SQL junto con dos paréntesis de apertura al principio, más 0x (que sirve para identificar el cifrado en el gestor de base de datos y que luego va a servir para devolverla impresa en la web en texto plano), más la cadena en Hex y dos cierre de paréntesis al final.

((0x3c7363726970743e616c6572742822636f64652d64697361737465722e626c6f6773706f742e636f6d22293c2f7363726970743e))

Quedando así.
http://www.local.com/test.php?Op=2-1+union+select+1,2,3,4,((0x3c7363726970743e616c6572742822636f64652d64697361737465722e626c6f6773706f742e636f6d22293c2f7363726970743e)),6