Retraso de tiempo en Inyección BLIND-SQL
Veamos los detalles que nos da la máquina con respecto a este laboratorio de Portswigger:
“Los resultados de la consulta SQL no se devuelven y la aplicación no responde de forma diferente en función de si la consulta devuelve filas o provoca un error. Sin embargo, dado que la consulta se ejecuta de forma síncrona, es posible activar retrasos de tiempo condicionales para inferir información.”
Recordemos que nuestro parámetro vulnerable será nuestra cookie “TrackingId”. Por lo tanto, en este apartado estaremos indagando sobre el retraso de tiempo en Inyección BLIND-SQL y recuperación de información.
Table of Contents
Toggle1) Verificar si existe alguna vulnerabilidad SQL y el tipo de base datos
Probemos lo siguiente:
También podríamos probar consultas como:
‘ ||(select ‘’ )||’ Mysql
‘ ||(select ‘’ from dual)||’ ORACLE (lo mismo para PostgreSQL)
Incluso podríamos probar para Microsoft SQL server.
Sin embargo, con dichas peticiones no recibiremos ningún mensaje de error y/o respuesta condicional. Tampoco nos devuelve el resultado de algún campo del sitio web o una pantalla en blanco. Es decir, el estado por parte del servidor hacia nuestra petición debe ser 200.
Por lo tanto, en base a esto, ya podemos ir pensando que se va a tratar de una vulnerabilidad del tipo Blind. Ahora bien, sabiendo que no obtenemos resultados del tipo “Respuesta condicional” y “Error condicional”, lo que podríamos suponer y probar, es que se trata de una vulnerabilidad donde nuestra información se basa en el tiempo de respuesta por parte del servidor.
Veamos esto con más detalle a continuación:
Como podemos ver, hemos ingresado la siguiente consulta:
‘||(select sleep(10)||’
Con esto, le avisamos al servidor que, en base a nuestro Request, queremos que el Response se tarde 10 segundos. Sin embargo, podemos ver que no hemos tenido éxito ya que, como se muestra remarcado en la imagen, el Response ha tardado 1.045 milisegundos (un poco más de un segundo).
Por tanto, quizá el problema esté en la base de datos, es decir, no haya Mysql por detrás. En tal caso, probemos con la siguiente consulta de PostreSQL:
Por lo tanto, podemos confirmar con la consulta ‘||(select pg_sleep(10))||’, que por detrás del sitio web hay una base de datos PostgreSQL. Se puede observar que el Response tardó 11,663 milisegundos (un poco más de 10 segundos) en base a nuestro Request. Cabe mencionar que también podríamos usar la siguiente consulta y obtendríamos el mismo resultado:
‘||(select pg_sleep(10)) – –
Recordar
Veamos lo que nos dice el sitio web de Portswigger (cheat-sheet):
“Puede causar un retraso de tiempo en la base de datos cuando se procesa la consulta. Lo siguiente causará un retraso de tiempo incondicional de 10 segundos.”
En base a esto, si nos vamos a la sección de Proxy de nuestro Burpsuit y le damos a “Forward”, veremos que hemos completado nuestro laboratorio.
2) Verificar la existencia de la tabla users y el usuario administrator
Para realizar condiciones con time-delays, veamos lo que nos dice el sitio web de Portswigger (cheat-sheet):
“Puede probar una sola condición booleana y activar un retraso de tiempo si la condición es verdadera.”
Teniendo esto en cuenta, podemos realizar la siguiente consulta para verificar la existencia de la tabla users:
Como podemos ver, primero se ejecuta la cláusula from, luego se ejecuta el select case y, como 1=0 es FALSE, se ejecutará la funcion else pg_sleep(1), la cual tarda un poco más de un segundo. De esta forma, podemos verificar que exista la tabla users. No obstante, también hay otra forma que nos permite verificar si existe el ususario administrator:
‘||(SELECT CASE WHEN (username = ‘administrator’) THEN pg_sleep(10) ELSE pg_sleep(1) END from users) — –
Veamos esto a continuación:
Por lo tanto, a partir de dicha consulta, podemos verificar que existe la table users y el usuario administrator. Se puede observar que el tiempo fue un poco más de 10 segundos.
3) Verificar la cantidad de caracteres que posee el password del usuario administrator
Recordemos que para este paso usamos:
‘||(SELECT CASE WHEN (username = ‘administrator’ and LENGTH(password)>1) THEN pg_sleep(10) ELSE pg_sleep(1) END from users) — –
Lo mismo podemos hacer colocándole (password)>30 y así sucesivamente. También, como vimos anteriormente, podríamos hacer uso de la sección Intruder y realizar un ataque de tipo Sniper. De igual modo, cualquier método que realicemos vamos a poder comprobar que la contraseña posee 20 caracteres. Para probar esto podemos hacer uso de (password)>=20. Veamos esto a continuación:
4) Enumerar caracter por caracter el password del usuario administrator
Para esto, y en base a las funciones que hemos estado viendo, podríamos generar la siguiente consulta:
‘||(SELECT CASE WHEN (username = ‘administrator’ and substring(password,1,1) = ’a’) THEN pg_sleep(3) ELSE pg_sleep(-1) END from users) — –
Por lo tanto, cuando el caracter a probar en dicha posicion sea correcto, tardará 3 segundos en colocarse. En caso contrario, con tiempo -1 segundo para que tarde lo menos posible, seguirá probando con el siguiente caracter para verificar si es el correcto.
Podríamos hacer uso del Intruder, por ejemplo, probando un ataque de tipo Sniper, caracter por caracter, o también, realizar un ataque Cluster Bomb. Sin embargo, hemos visto que tenemos más rendimiento, en cuanto a tiempo y velocidad, con un script en Python.
Script en Python con Retraso de Tiempo en Inyección BLIND-SQL
Para ello nos crearemos un archivo cuyo nombre sea blind-sqli-Ctime.py y, a través de un script como vimos en Conditional Response y Conditional Error, definiremos la función. BruteForce():
Recordemos colocar la función substring en (password,%d,1) = ‘%s’ ya que, %d hace referencia a la posición del password y el ’%s’ al string, es decir, el caracter a probar.
También, podríamos haber utilizado la siguiente consulta:
‘||(SELECT CASE WHEN substring(password,1,1) = ’a’ THEN pg_sleep(2) ELSE pg_sleep(-1) END from users where username = ‘administrator’) — –
Recordemos ejecutar el script a través de las siguientes líneas:
Ahora bien, procedamos con nuestro ataque:
Por lo tanto, procedemos a realizar un log in con dicha contraseña:
Como resultado, tenemos nuestro laboratorio resuelto!
Si desea saber un poco más sobre el uso de Python en base de datos puede ver nuestro artículo donde explicación distintos métodos y funciones.