Inyectando subconsultas MySQL

Hubo un CTF en el que la intención era extraer información a partir de inyecciones SQL, expliqué en http://sniffer.comparte.tips/solucionario-del-ctf-lucha-contra-el-cybercrimen/ cómo logré obtener parte de la información que me pedían, sin embargo estaba pendiente la publicación de la técnica usada para extraer los últimos dos datos pendientes.

Partiendo de lo básico, asumiendo que una consulta del tipo SELECT * FROM usuarios arroja algo como:

  Continue reading “Inyectando subconsultas MySQL”

[Des]Configurar WiFi con la ayuda UNE

Esta publicación la tenía pensada desde hace varios meses, sin embargo solo la comparto en este momento ya que desde UNE me responden una comunicación así: “Nuestro personal de desarrollo nos informa que dicha vulnerabilidad ya ha sido controlada, tienes forma de validar?”.

Para entrar en contexto empiezo compartiendo una de las publicaciones que hizo UNE para promocionar un nuevo desarrollo, el portal “Ayuda UNE”:

Continue reading “[Des]Configurar WiFi con la ayuda UNE”

Yo me llamo: Bot fanático

Yo me llamo es un concurso que busca el doble exacto de algún artista/grupo musical, para ello debe ir seleccionando en cada fase a los más idénticos. Yo me interesé en buscar el doble exacto de los fanático votando, y lo puedes encontrar acá: http://goo.gl/gOP7lq (archivo que contiene un software que en teoría debe votar por el artista que elijas).

Todo inició cuando en una ocasión que mientras mi papá veía el programa escuché que el presentador invitaba a votar todas las veces que quiera, en contraste, en la aplicación solo se podía votar 50 veces. El resultado de votar es algo así:

 

 

Ahora el reto está en ¿cómo votar más de 50 veces?, las información que conocía era:

  • No se requería iniciar sesión en ningún sistema.
  • Se podía votar 50 veces por dispositivo (decía mi papá que votó en el laptop y en el celular)

El paso siguiente es analizar cómo se comporta una votación, que se resume en la siguiente imagen:

 

 

Luego de hacer la votación respectiva, de consumir los votos, el status mostrado es “limit”,  y además si se altera la levemente la petición se puede obtener un error:

 

 

Si observan la diferencia entre las peticiones pueden notar que la diferencia está en una cabecera que hace falta y por ende ha de validarse en el servidor. Hace falta enviar el correcto “Referer”, cabecera que indica quién creó el vínculo al recurso solicitado, es decir para este caso el sitio web http://ymll.caracoltv.com/votaciones_web/.

 

 

Hasta acá entonces es simple entender que lo que se requiere para que un voto sea válido es:

  • Hacer una petición al recurso que registra el voto, enviando como parámetro la identificación del artista/grupo por el que se está votando.
  • Indicar el “Referer” adecuado, porque es validado en el servidor.

Y para identificar qué dispositivo está votando usan el valor enviado como “User-Agent”, que es una cadena de texto que identifica al agente (entiéndase dispositivo) ante el servidor. Pueden observar como en las siguientes peticiones la respuesta obtenida es que en ambos casos faltan 49 votos:

 

 

Cuando el sistema de votación es masivo de forma común se encuentran integrados con facebook, es menos común que tengan su propio sistema de autenticación y voto, pero se me hizo bastante particular lo que hay en este concurso: cuenta cincuenta veces una “firma” IP + User-Agent.

Siempre me han llamado la atención los sistemas de votación y de encuestas, ya que la información que se obtenga se convertirá en insumo para la toma de alguna decisión, es decir, en algunos casos solo se toma como una opinión que puede ser tenida en cuenta y en otras es más radical y definitivo ya que determina (sin considerar otra opinión) la decisión.

En este caso el artista/grupo que obtenga la menor cantidad de votos es eliminado del concurso. En este caso ¿qué ocurre si hay bots votando? ¿se puede obtener el doble de los fanáticos votando?

La primera prueba fue simple, construir una petición y enviarla las 50 veces que es permitido, acto seguido cambiar el “User-Agent” y ejecutar de nuevo:

 

 

El análisis que derivó en ese pequeño código lo logré en unos 20 minutos, y considerando que las votaciones duraron cerca de 45 minutos tuve tiempo suficiente para analizar un poco más a fondo el sistema de votación y recopilar la información necesaria para hacer una aplicación que en teoría deberá validar el estado de las votaciones, dar a elegir el concursante a votar y en última instancia votar. La aplicación la encuentran en http://goo.gl/gOP7lq y en el momento en que estén habilitadas las votaciones deberá verse similar a:

El software no ha sido probado durante un show en vivo, en teoría funciona, y de ser así votar te va a gustar el doble.

Pd: Independiente de como funcione el archivo NO haré modificaciones, no daré soporte, no estoy a favor ni en contra de ningún concursante.

Actualización:

Gracias a los que probaron y usaron la aplicación, el código publicado como PoC sí funcionó, tuvo una buena acogida incluso del personal encargado del concurso ya que ellos hicieron unas leves modificaciones en sus servidores y el código para que el Bot no funcionara. Si tienes un conocimiento en programación podrás ajustar la url a la que se hace el voto según la lógica planteada en http://ymll.caracoltv.com/votaciones_web/js/client.js (debes hacerlo contra-reloj ya que esta URL solo está habilitada durante el tiempo que están las votaciones habilitadas).

Click=Ejecución del bot (día del show en vivo)

#SíSeLlama bot fanático

Solucionario del CTF “Lucha contra el cybercrimen”

Leí vía correo la invitación a un CTF que diseñó Juan Valencia, se podía acceder desde http://ctf-lcc.info/, y entre las instrucciones decía: “las pistas se entregaran a medida que transcurre el juego via twitter (@CTFLCC)”, así que procedí a mirar si habían pistas publicadas ya que mi intención inicial era simplemente hacerle seguimiento a un CTF local.

Lo que realmente hizo que empezara a jugar es el hecho de que estaba “protegido” por un WAF!

Ahora que tenía un reto personal, leí las instrucciones y de los 1000 puntos a obtener empecé por la parte que identifiqué como la más sencilla, la segunda parte, que decía:

“La segunda parte consiste en un sencillo CTF (Capture de flag), tienes que encontrar cuatro banderas, cada una de estas tiene un valor de 100 puntos.
Las banderas tienen la siguiente estructura THE_KEY: “XXXX” o LA KEY ES “XXXX” donde “XXXX” es el valor de la bandera y corresponde al nombre de un libro. Ejm: LA KEY ES “CRIMENYCASTIGO”.
Para encontrar las banderas debes buscar metadatos, utilizar un proxy HTTP o Firebug e inspeccionar el HTML.”

Las cuatro banderas las identifiqué en el siguiente orden:

  1. En el código fuente del index se observa THE_KEY:ELCUARTETODEALEJANDRIA.
  2. Hay una cookie llamada THE_KEY con el valor a8217d1f9bc025b3bfe8d1c61eb21fa6.
  3. En la imagen de logo view-source:http://ctf-lcc.info/images/logo.gif se observa el texto LA KEY ES “BUDABLUES”.
  4. Ayudado por que permitía listado de directorios analizo todas las imágenes y observo en view-source:http://ctf-lcc.info/uploads/09Feb2014.jpg el texto bGEga2V5IGVzIDogIkVMUEFMQUNJT0RFTEFMVU5BIg==, que al decodificar el base 64 se lee ‘la key es : “ELPALACIODELALUNA”‘.

Una vez listas las cuatro banderas (o tres porque de la segunda no encontré el texto en claro), venía el reto de extraer una información del sitio, dicha información equivalía a 600 puntos (100 puntos por cada dato):

  1. Nombre real de “Cuchillo”.
  2. Correo electrónico de “Cuchillo”.
  3. Dirección física de “Cuchillo”.
  4. Número telefónico de “Cuchillo”.
  5. Dirección IP de conexión de “Cuchillo”.
  6. Número celular del administrador del sitio.
Al analizar los objetivos se hace evidente que lo que se desea es lograr acceso a los datos, y para ello hay varios caminos como lo son:
  • Obtener las credenciales/cookies del administrador: Requiere interacción del administrador, ya sea que esté en sitio y sea víctima de XSS o que entregue sus credenciales en un ataque de phishing.
  • Crear un usuario en el sistema y elevar privilegios: Aunque en la plataforma se puede alterar la sesión para quedar autenticado como otro usuario, no se logró una cuenta administradora.
  • Inyectar código SQL: Hay que lograr sobrepasar las protecciones que brinda el WAF Incapsula.
El hecho de que la aplicación esté “protegida” por un WAF lo que hace es que, de existir una vulnerabilidad, podría dificultar su explotación. No fue una excepción en este caso, ya que al parecer se hacía un análisis de la composición de la URL para tomar acción sobre la petición, y si la calificaba como “peligrosa” actuaba según configuración (tenía definido bloquear al usuario).

Una forma inicial de validar si un parámetro es vulnerable a una inyección SQL es añadir una comilla, y luego de ahí proceder con un operador OR, con comandos como UNION, hacer otros SELECT, y así se va construyendo una inyección. Para este caso el WAF identificó las primeras pruebas como “peligrosas” y procedió a bloquear.

Una forma adicional de verificar si existe una posible inyección es hacer una resta, por ejemplo:

  • ?articulo=1 -> Muestra el primer mensaje.
  • ?articulo=2 -> Muestra el segundo mensaje.
  • ?articulo=10 -> Muestra un error o se ve en blanco ya que no existe el mensaje 10.
  • ?articulo=10-8 -> Muestra el segundo mensaje.
  • ?articulo=2-1 -> Muestra el primer mensaje.
La inyección tiene lugar cuando lo que envía el usuario es ejecutado en el servidor, en el caso de que espere un valor numérico se podrá inyectar la resta y se logrará que primero calcule la sustracción y luego ejecute la consulta. Si el valor que espera recibir es un texto no hará cálculo alguno ya que quedará como texto “2-1”.
De manera particular en esta plataforma, al hacer /ViewItem.php?ItemNum=530557754-1 obtenía el error:

Database error: Invalid SQL: select ti.template from templates_items ti, items i where i.ItemNum=’530557754-1′ and (ti.cat_id=) and ti.active=1 and ti.admin_override=1 ORDER BY ti.cat_id DESC LIMIT 1
MySQL Error: 1064 (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘) and ti.active=1 and ti.admin_override=1 ORDER BY ti.cat_id DESC LIMIT 1’ at line 1)
Session halted.

Sobre dicha URL se podría empezar a trabajar en una inyección, pero por la información que se necesitaba y al desconocer la estructura de la base de datos se dificultaba ejecutar las consultas, esto debido a que el WAF bloqueaba de manera constante, posiblemente al identificar palabras claves como UNION, SELECT, information_schema, entre otras.

La solución fue buscar otra URL que facilitara el proceso de inyección. Dicha URL fue /ViewCat.php?s_user_id=Cuchillo, ya que al hacer una inyección se obtenía un error del mismo estilo:

Database error: Invalid SQL: SELECT user_id FROM users WHERE user_login=’Cuchillo”
MySQL Error: 1064 (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ”’ at line 1)
Session halted.

La diferencia está al notar que estamos manipulando directamente la tabla “users”, así podremos evitar el uso de “comandos bloqueados” y dedicarnos a retocar la consulta. Algo a considerar es que lo que uno envía es el nombre del usuario, la consulta busca su id y la respuesta es todos los objetos que dicho usuario está ofreciendo, de no existir el usuario o no tener objetos no muestra resultados. Si ponemos esto en ejemplo sería:

  • Primer caso:
  1. Enviamos el parámetro s_user_id con el valor de “Cuchillo”.
  2. La primer consulta trae la identificación del usuario “Cuchillo”.
  3. La segunda consulta busca los objetos del usuario con la identificación obtenida, la de “Cuchillo”.
  • Segundo caso:
  1. Enviamos el parámetro s_user_id con el valor de “Cuchillo+SQLi”.
  2. La primer consulta trae la identificación del usuario “Cuchillo” y ejecuta el código SQL inyectado.
  3. La segunda consulta busca los objetos del usuario con la identificación obtenida, la de “Cuchillo”.
Al observar, en ambos casos el punto 3 es igual, 1 y 2 no. Si lo anterior es claro, nos encontramos con la posibilidad de inyectar en una consulta intermedia, lo que quiere decir que el método de explotación es a ciegas. Podremos inyectar de forma que si la consulta es verdadera muestre los objetos de “Cuchillo”, de ser falsa no muestre nada. En la práctica sería:
  • /ViewCat.php?s_user_id=Cuchillo’ and true — –
  • /ViewCat.php?s_user_id=Cuchillo’ and false — –

Ambas consultas son permitidas por el WAF!
Hay que poner atención a que el operador lógico que une la condición es un AND, pero analicemos otra consulta:

  • /ViewCat.php?s_user_id=Cuchillo’ and length(“ab”)-1 — –
  • /ViewCat.php?s_user_id=Cuchillo’ and length(“a”)-1 — –

Lo que hace es tomar la longitud del texto “a” o “ab” y restarle 1. Cuándo la resta sea igual a 0 será el equivalente a FALSE, en otro caso la resta será equivalente a TRUE, entonces si hacemos:

  • length(user_password)-1 -> TRUE
  • length(user_password)-2 -> TRUE
  • length(user_password)-3 -> TRUE
  • length(user_password)-4 -> TRUE
  • length(user_password)-5 -> TRUE
  • length(user_password)-6 -> TRUE
  • length(user_password)-7 -> FALSE
Lo primero a aclarar es que el nombre de la columna era trivial (cuando conocía “user_id” y “user_login”), en caso de no serlo se podía probar distintas combinaciones hasta que no se tenga el error de “columna desconocida”. Ahora sí, aclarando el ejercicio anterior, con la inyección logramos identificar que la contraseña usada por el usuario “Cuchillo” tiene una longitud de siete caracteres.
La contraseña puede tener todo tipo de caracteres, ¿qué tan segura será?. Una forma de optimización sencilla (hay muchas formas y muchas mejores) es codificar la contraseña en hexadecimal, esto hará que los caracteres usados sean entre 16 posibles. Hagamos una prueba teórica:
  • Si la clave es “cL@/3!” debemos considerar probar más de 90 caracteres en las 7 posiciones del texto; entre minúsculas, mayúsculas, números y símbolos. Probar todas implica 630 (90*7) peticiones.
  • Si la clave es “634c405c2f3321” debemos considerar probar 16 caracteres en las 14 posiciones del texto; entre los números y las primeras seis letras del alfabeto. Probar todas implica 224 (16*14) peticiones.

Para lograr extraer la contraseña haremos la inyección /ViewCat.php?s_user_id=Cuchillo’ and ASCII(substr(hex(user_password),1,1))-48 — – donde:

  • Codificamos en hexadecimal la contraseña “hex(user_password)”.
  • Extraemos el carácter que está en la primera posición “substr($hex,1,1)”.
  • Convertimos el carácter a su equivalente numérico “ASCII($char)”.
  • Restamos un valor entre 48 y 57 (del 1 al 9) o entre 97 y 102 (entre a y f).
  • Si la resta es 0 el resultado será un FALSE y no se verán los objetos de “Cuchillo”.

Para iterar basta con cambiar el valor a restar y cuando encontremos el valor deseado ajustamos el parámetro de la función substr para continuar extrayendo la contraseña, es decir:

  • El primer carácter se logra con /ViewCat.php?s_user_id=Cuchillo’ and ASCII(substr(hex(user_password),1,1))-55 — –
  • El sexto carácter se logra con /ViewCat.php?s_user_id=Cuchillo’ and ASCII(substr(hex(user_password),6,1))-50 — –
  • El décimo cuarto carácter se logra con /ViewCat.php?s_user_id=Cuchillo’ and ASCII(substr(hex(user_password),14,1))-49 — –

Los valores obtenidos al final son:

  • 55 51 55 53 54 50 55 50 54 49 55 52 54 49.
  • Que al convertir dichos ASCII equivalen a 7 3 7 5 6 2 7 2 6 1 7 4 6 1.
  • Que al convertir el hexadecimal equivale a “subrata”.

Una vez se inicia sesión con el usuario “Cuchillo” y la clave “subrata” podremos ver en el sitio los datos que tiene en su perfil:

 

 

Llegados a este punto, para lograr los 1000 puntos del CTF solo hace falta la dirección IP de conexión de “Cuchillo” y el número celular del administrador del sitio. Según una pista que fue publicada se puede hacer uso de http://www.exploit-db.com/exploits/31140/, pero la resolución que explicaré merece una publicación diferente (que pueden leer en http://sniffer.comparte.tips/inyectando-subconsultas-mysql/).

El concurso que perdió UNE

Todo empezó (al menos para mí) el 10 de enero, cuando en mi TL de twitter observo el siguiente tuit hecho por @UNEMejorJuntos (que también publicaron en facebook):


Queriendo averiguar en qué consistía el concurso visito www.une.com.co/videotienda y además de la información de la imagen encuentro dos enlaces, a una aplicación y a un documento en PDF con los términos y condiciones del concurso, dicho PDF se encontraba en http://www.une.com.co/videotienda/terminos/terminos-y-condiciones.pdf, y digo encontraba porque de forma inesperada (o al menos para mí) el recurso fue borrado y solo muestra un error 404 (Página no encontrada).
Los términos y condiciones publicados lucían así:

Y claramente se comprometían a que (Numeral 5, punto 4) “La publicación del ganador será el 10 de febrero de 2014”, razón por la que decidí revisar el concurso el día 11 de febrero (tenía un recordatorio xD ), y decido preguntar vía twitter ¿quién es el ganador?, además estaba alarmado por el contenido borrado!

Contenido que por cierto se podía ver aún en la caché de google:

Se supone que desde ese día están “validando la información”

Una pregunta rápida sería ¿no había una responsabilidad contraída desde el momento en que le dan vigencia al concurso?, lo que me molesta es que NO se pronuncien, considero (sin ser abogado) que están perjudicando dolosamente el derecho de los concursantes.

Ahora, ¿cómo era el concurso?

La aplicación en la que se basó el concurso se accedía desde https://www.facebook.com/UNEMejorjuntos/app_793957187297213, aunque también se puede usar desde https://www.facebook.com/nativamundo/app_793957187297213, que lo primero que hace es solicitar los datos del suscriptor a través de http://apps.grupovideobase.net/une/trivias/signup.php y luego se puede participar en la trivia:

Supongo que UNE empezó a “molestarse” cuando (al igual que yo) observaba que algunos participantes respondían la única pregunta que hacían (la respuesta es “Vaso de crispetas”) en un tiempo de ¡cero segundos!

Entonces ¿cómo hacía yo para quedar primero en el ranking general? (El premio es entregado al participante mejor ubicado en la tabla de resultados que cumpla con el alquiler de una película, no tenga facturas pendientes por pagar, entre otras condiciones).

La respuesta fue sencilla, hacer un mejor tiempo que 0 segundos es ¡lograr responder en -1 segundo!, así que me puse un reto al estilo Chuck Norris.

Alquilé la respectiva película en la videotienda que brinda la IPTV y de ahí respondí la trivia en el menor tiempo!

El premio es un SMART TV Samsung de 55 pulgadas (UNE tiene publicado en su tienda uno de estas características con un costo de $9’125.000 $5’550.000 COP), un buen premio sobre el que deberían pronunciarse, pero ¿será que prefirieron borrar la información de TyC en lugar de finalizar correctamente el concurso? ¿será que no bastó el tiempo entre el 1 y 10 de febrero para validar de forma interna el ganador? ¿será que no alcanzaron a promocionar lo suficiente la videotienda (para recibir alquileres de películas) como para “librar” el costo del premio?

Lo único que se me ocurre es que entre las distintas estrategias que ha usado UNE para fidelizar a los clientes, en esta, al no haber ganador y por su silencio siento a UNE como el perdedor.