Lathack

Error condicional en Inyección BLIND-SQL

Error Condicional en Inyección BLIND-SQL

Introducción

En este apartado veremos uno de los fallo de seguridad más comunes en base de datos. Estamos hablando del Error Condicional en Inyección BLIND-SQL en la máquina de Portswigger. Como su nombre lo indica, y como vimos anteriormente, nos basaremos en un mensaje por parte del servidor. En este caso, un error como respuesta. Como hemos visto anteriormente, dichos mensajes o pantallas en blanco, pueden darnos mucha información.

Las consignas de esta máquina son iguales a la anterior (Respuesta condicional). Solo que esta vez, NO nos basaremos en un mensaje en particular. Sino en un mensaje de error “Internal Server Error” cuyo código de estado es 500. El objetivo de realizar esta máquina es como el anterior, debemos realizar un acceso como usuario administrator. Para esto vamos a basarnos en los siguientes pasos:

1) Verificar la vulnerabilidad SQLI:

Primero probaremos ingresando solo una comilla () para verificar qué mensaje obtenemos como resultado:

Error Condicional en Inyección BLIND-SQL

Como vemos, nos devuelve un código de estado 500 cuyo mensaje es “Internal server error”. Esto es un claro ejemplo de error condicional en consultas de inyección blind-sql. Por lo tanto, podríamos seguir probando ‘ or 1=1 — – para ver qué resultado obtenemos:

Notamos que no nos devuelve ningún mensaje de error ni nada parecido. Por lo tanto, ya podemos ir pensando que se trata de una inyección del tipo Blind-SQL.

Ahora bien, podemos suponer que por detrás hay una query como la siguiente:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT

Por lo tanto, cuando colocamos una comilla () generamos un error de sintaxis. Seguramente por eso es que obtuvimos un mensaje de error. Sin embargo, ¿Qué ocurre si colocamos tres comillas (‘’’)?

La consulta se vería de la siguiente manera:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’’’

Como podemos ver, dicha consulta también posee un error de sintaxis ya que, abrimos una comilla y luego la cerramos con la segunda, quedando la tercera sola sin ninguna comilla que la cierre. Verifiquemos esto:

Error Condicional en Inyección BLIND-SQL

Por lo tanto, si colocáramos solo dos comillas (‘’) no tendríamos como respuesta ningún mensaje de error. Teniendo esto cuenta, podríamos aprovecharnos de dichas comillas para poder concatenar dos consultas. Para esto, haremos uso de los pipes. La consulta nos quedaría de la siguiente manera:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select ‘’) ||’

Entonces podríamos basarnos en esta query para concatenar dichas consultas ya que, dada su sintaxis, no estamos cometiendo ningún error. Por lo tanto, no debería aparecernos ningún mensaje de error:

Tener en cuenta

Como podemos observar, hemos obtenido un mensaje de error. Sin embargo, ¡No debemos olvidarnos que los errores son mensajes importantes también! Por tanto, si la sintaxis está bien hecha y hemos recibido dicho mensaje, lo más seguro es que por detrás haya una base de datos que no sea MySQL.

Probemos la siguiente consulta en caso de que se trate de una base de datos ORACLE:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select ‘’ from dual) ||’

Error Condicional en Inyección BLIND-SQL

Hemos obtenido un código de estado 200 y ningún mensaje de error. Por lo tanto, con esto podemos verificar que por detrás se encuentra una base de datos ORACLE.

Recordar

Veamos lo que nos dice el sitio cheat-sheeat de Portswigger:

Puede concatenar varias cadenas juntas para hacer una sola cadena

SLQ Blind Injection Vulnerability

2) Verificar la existencia de la tabla users.

Para esto podemos hacer uso de la siguiente consulta:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select ‘’ from users) ||’

Error Condicional en Inyección BLIND-SQL

Teniendo en cuenta este error, lo que podemos hacer ahora es hacer uso de la claúsula rownum.

Cláusula rownum

Esta función nos permite elegir la cantidad de filas o registros que queremos visualizar en base a una consulta. Como no sabemos la cantidad de filas que pueda haber en la tabla users, lo que podemos hacer es colocar rownum = 1 ya que, en caso de existir dicha tabla, lo más seguro es que por lo menos posea una fila.

Veamos esto a continuación:

SLQ Blind Injection Vulnerability

¡Podemos verificar que existe la tabla users!

3) Verificar la existencia del usuario administrator.

Lo primero que se nos viene a la mente sería realizar la siguiente consulta:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select ‘’ from users where username = ‘administrator’) ||’

Y lo más seguro es que recibamos un código de estado 200. Por tanto, podemos pensar que estamos en lo correcto y que existe el usuario administrator. Sin embargo, esto no es del todo seguro, ya que si dicho usuario NO existe en la base de datos, simplemente NO se ejecutará la parte seleccionada de la declaración. Por lo tanto, no nos dará un error de ninguna manera, y debido a esto, no podremos saber si ese usuario realmente existe en la base de datos o no.

Por tal caso, haremos uso de la función CASE.

Uso del Condicional CASE

El condicional CASE permite asignar un valor a una columna tomando como referencia otro valor de la tabla. Por cada valor o grupo de valores existe un WHEN y un THEN. Si encontramos un valor coincidente en algún WHEN, ejecutaremos el THEN correspondiente al mismo. Caso contrario, se ejecuta el ELSE. Este condicional se debe cerrar con la palabra END para indicar que el CASE ha finalizado.

Ejemplos

El siguiente ejemplo asigna un posible valor (CARO / BARATO / EQUILIBRADO) en una columna con el nombre Categoría, tomando como referencia los valores de la columna precio de una tabla con el nombre productos.

SELECT nombre, precio, CASE WHEN precio < 10 THEN ‘BARATO’ WHEN precio BETWEEN 10 AND 20 THEN ‘EQUILIBRADO’ ELSE ‘CARO’ END as Categoria FROM productos;

Ahora bien, usaremos esta función a nuestro favor, pero esta vez el mensaje “Internal server error” será el que nos ayude a comprobar si el usuario administrator existe:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE ‘’ END from dual) ||’

Modo de uso
  1. Con 1=0 le estamos pasando un valor de tipo FALSE al sistema

  2. Usando TO_CHAR convertimos un tipo de dato, o valor interno, en un valor de ‘tipo de cadena especificado’, o tipo string, por la cadena de formato. Por ejemplo datos de fecha o marcas de tiempo.

  3. Con respecto a 1/0 es un valor de tipo FALSE

Lo que estamos haciendo aquí es decir que cuando A (1 = 1), que siempre será TRUE, realice esta función, luego se ejecutará C (1/0) con dicho parámetro no válido, y obtendrá un error.

Ahora bien, en el caso que A sea 1=0, entonces no debería ejecutarse la función C en absoluto. Es decir, debería llegar a la declaración else y luego generar una cadena vacía, lo que significa que obtendríamos una respuesta 200 porque no recibimos un error.

Verifiquemos esto:

Error Condicional en Inyección BLIND-SQL

Teniendo esto en cuenta, procedemos a realizar la siguiente consulta:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE ‘’ END from users where username = ‘administrator’) ||’

Orden de ejecución

La cláusula from se evalúa primero antes que la cláusula select por tanto, cuando decimos que en la tabla users, donde el username es igual a administrator y, si existiera en la base de datos, la siguiente acción a ejecutar sería A (1=1). Entonces, como A es TRUE, el siguiente paso a ejecturse será C y, como C es FALSE, nos devolverá un mensaje de error.

Como podemos ver, el usuario “administrator” si existe.

Ahora bien, a modo de ejemplo, si el valor de A hubiese sido 1=0, un valor FALSE, el siguiente paso a ejecutarse hubiese sido ELSE ´´ y, como es un valor vacío ya que no colocamos nada dentro de las comillas, nos daría por defecto un resultado con un código 200.

Rercordar

Veamos lo que nos dice el sitio web cheat-sheet de Portswigger:

“Puede probar una sola condición booleana y desencadenar un error de base de datos si la condición es verdadera.”

Error Condicional en Inyección BLIND-SQL

4) Verificar la cantidad de caracteres y la existencia del campo password.

En el caso de querer verificar la existencia de la tabla ‘password’, recordemos que podemos aplicar la función rownum como hicimos con la tabla users. Ahora, sabemos por la información del laboratorio que la cantidad de caracteres son 20. Sin embargo, en el caso de no saber dicha información y querer saber la cantidad de caracteres para dicha columna, nos volveremos a basar en el mensaje de error usándolo a nuestro a favor. Por tanto, usaremos el siguiente script:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE ‘’ END from users where username = ‘administrator’ and LENGTH(password)>1) ||’

Si aplicamos dicha consulta, nos devolverá un mensaje “Internal server error”. Por lo tanto, podemos verificar que el password posee más de un carácter. Y, si colocamos LENGTH(password)>30 podremos comprobar que nos devuelve un mensaje de estado 200. Por lo tanto, los caracteres de la contraseña del usuario administrator son mayores a 1 y menores a 30.

Ahora bien, podríamos seguir usando esto y verificar por cada caracter para saber la cantidad justa. Sin embargo, una forma un poco más eficaz, sería enviar dicha información a la sección Intruder de nuestro BurpSuit y realizar los pasos que veremos a continuación.

Ataque tipo Sniper con Error Condicional en Inyección BLIND-SQL

Primero enviamos nuestra petición o response al intrude con Ctrl+i o click derecho y “Send to intruder”. Luego procedemos a realizar los pasos marcados en orden numérico como se muestra en la siguiente imagen:

Realizaremos un ataque de tipo Sniper, por tanto, cambiaremos el valor remarcado de 30 a 1 y luego elegiremos dicho ataque. Una vez finalizado esto, nos dirigimos a la sección Payloads.

Error Condicional en Inyección BLIND-SQL

Una vez dentro de la sección Payloads elegiremos las opciones tal cual se muestran y, finalmente, empezamos la operación dando click en el botón “Start attack” como se muestra en la siguiente imagen:

Por lo tanto, prestemos atención a la siguiente imagen una vez finalizada nuestra búsqueda:

Error Condicional en Inyección BLIND-SQL

Vemos que para una posición password>19 nos devuelve un estado 500, es decir, “Internal server error”. Sin embargo, para la posición password>20 nos devuelve un estado 200. En base a esto, podemos sacar la conclusión de que la cantidad de caracteres del usuario administrator es mayor a 19 pero no mayor a 20. Por lo tanto, la posición correcta es password=20.

Podríamos verificar esto realizando la siguiente consulta:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE ‘’ END from users where username = ‘administrator’ and LENGTH(password)>=20) ||’

Por tanto, ya sabemos que dicha contraseña posee 20 caracteres.

5) Verificar la contraseña del usuario administrator

Como vimos en el ejercicio “Respuesta Condicional” usaremos la siguiente consulta para saber esto:

SELECT * FROM tabla WHERE TrackindID = ‘06nstzWJgo9cQoT’|| (select CASE WHEN SUBSTR(password,1,1) = ’a’ THEN TO_CHAR(1/0) ELSE ‘’ END from users where username = ‘administrator’) ||’

Como podemos observar, las únicas diferencias son que, en este caso estamos usando el condicional CASE y hemos cambiado la función substring de Mysql, por SUBSTR de ORACLE.

Script en Python para uso de Error Condicional en Inyección BLIND-SQL

Teniendo en cuenta el apartado anterior, podríamos hacer uso de un Cluster Bomb en la sección Intruder de nuestro BurpSuit. No obstante, esto nos tomaría más tiempo. Por lo tanto, nos basaremos en el mismo script de Python que usamos anteriormente. Para esto crearemos el archivo blind-sqli-CE.py (No olvidar dar permisos de ejecución).

En esta primera parte declaramos la función BruteForce():

Podemos observar que no solo han cambiado los valores de url, TrackingId y Session, sino también nuestro mensaje de error. Es decir, para saber cuál es el caracter correcto, el sistema probará uno a uno hasta que haga un match con un estado 500 como response. Sumado esto, recordemos que ejecutaremos y pararemos la función de la siguiente manera:

Por lo tanto, en base a esto, guardaremos dicho script en un archivo llamado blind-sqli-CE.py y lo ejecutaremos de la siguiente manera:

Error Condicional en Inyección BLIND-SQL

Ahora bien, procederemos a colocar usuario y la contraseña encontrada en “My account” dentro del laboratorio:

 

Y obtenemos el siguiente resultado:

SLQ Blind Injection Vulnerability

Como podemos ver, ¡Hemos tenido éxito con nuestro log in!

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

cinco × 1 =

Lathack
Scroll al inicio