Curiosidades De Hackers
OWASP TOP 10

Inyecciones SQL (4/4). Inyecciones SQL a Ciegas(BLIND SQL); Explicación y PoC


    En esta serie de 4 partes, estaré explicando los diferentes tipos de Inyecciones SQL que hay de una forma muy básica a nivel principiante, en la cual iremos aumentando la dificultad capitulo a capitulo.

    Y en esta ultima parte estaré explicando las inyecciones SQL a ciegas(BLIND SQL)

Pero, antes que nada. ¿Qué es una inyección SQL?

    Una inyección SQL consiste en la inserción de código SQL por medio de los datos de entrada desde la parte del cliente hacia la aplicación. Es decir, por medio de la inserción de este código el atacante puede modificar las consultar originales que debe realizar la aplicación y ejecutar otras totalmente distintas con la intención de acceder a la herramienta, obtener información de alguna de las tablas o borrar los datos almacenados, entre otras muchas cosas.

    Como consecuencias de estos ataques y dependiendo de los privilegios que tenga el usuario de la base de datos bajo el que se ejecutan las consultas, se podría acceder no sólo a las tablas relacionadas con la aplicación, sino también a otras tablas pertenecientes a otras bases de datos alojadas en ese mismo servidor.

    Lo comentado anteriormente es posible gracias a que el uso de ciertos caracteres en los campos de entrada de información por parte del usuario, ya sea mediante el uso de los campos de los formularios que son enviados al servidor mediante POST o bien por medio de los datos enviados mediante GET en las urls de las páginas web, posibilitan coordinar varias consultas SQL o ignorar el resto de la consulta, permitiendo ejecutar la consulta que elija, de ahí que sea necesario realizar un filtrado de esos datos enviados para evitar problemas.

    Así lo explique en un articulo anterior sobre Inyecciones SQL, con mayor detalle teórico.

¿Qué es una inyección SQL a ciegas (Blind SQL Injection) ?

    La inyección SQL a ciegas (Blind SQL Injection) es una técnica de ataque que se basa en analizar la respuesta de la página web a entradas específicas para inferir información sobre la base de datos subyacente.

    Generalmente, los ataques de inyección SQL ocurren debido a la falta de validación de los parámetros de entrada, que son valores enviados desde el cliente al servidor web. Estos parámetros pueden incluir campos de consulta GET pasados a través de la URL, campos de formularios enviados mediante el método POST, variables almacenadas en cookies, valores en los encabezados HTTP y parámetros de llamadas a funciones JavaScript. La falta de un control adecuado sobre estos parámetros puede permitir que se inyecte código SQL malicioso, explotando vulnerabilidades en la aplicación web.

    La técnica de inyección SQL a ciegas se basa en inyectar consultas SQL verdaderas o falsas y observar las respuestas o el comportamiento de la página web. Este ataque es útil cuando la aplicación web muestra errores genéricos o responde de manera diferente ante consultas SQL verdaderas o falsas.

    En una inyección SQL estándar, la base de datos devuelve datos que se muestran en la página web, como el contenido almacenado. En contraste, la inyección SQL a ciegas se utiliza cuando la base de datos no muestra datos directamente en la página web, es decir, no hay una salida visible. En estos casos, el ataque se realiza formulando preguntas verdaderas o falsas a la base de datos y analizando cómo cambia el comportamiento de la página web para inferir información.

    El primer paso en la inyección SQL a ciegas es identificar los parámetros que podrían ser utilizados en una consulta SQL para interactuar con la base de datos subyacente. En el ejemplo dado, descubrimos que el método «/home» recupera datos usando el `pageID` y muestra el contenido asociado.

Ahora, veamos si podemos provocar un error inyectando una comilla simple. Esto nos ayudará a verificar si la aplicación maneja incorrectamente las entradas, lo que podría ser indicativo de una vulnerabilidad en la forma en que se procesan las consultas SQL.

Sin embargo, todavía no podemos ver el resultado esperado ya que la aplicación muestra una página de error 404. Ahora necesitamos inyectar operadores lógicos para determinar si la aplicación es vulnerable a inyecciones SQL.

Primero, inyectamos un operador lógico que sea verdadero, como `1=1`. Si la aplicación funciona como se espera y no muestra errores, esto confirmará que la inyección SQL está teniendo efecto y que la vulnerabilidad podría estar presente.

Luego de eso, inyectamos un operador lógico que sea falso, como por ejemplo `1=2`. Esto debería provocar que la aplicación devuelva un error. Al hacerlo, estamos evaluando la respuesta de la aplicación para confirmar que la inyección SQL está afectando la consulta de manera esperada y que la vulnerabilidad es confirmada.

Al realizar esta prueba, confirmamos que la aplicación es vulnerable a inyecciones SQL.

Esto ocurre porque la entrada proporcionada por el usuario se concatena directamente en la consulta SQL sin el debido manejo o validación, lo que permite que se manipule la consulta de manera no intencionada. Este tipo de vulnerabilidad puede ser explotada para obtener información no autorizada o realizar otras acciones maliciosas en la base de datos.db.execute(‘SELECT pageId, title, content FROM pages WHERE pageId=’+pageId)    

Ahora que hemos confirmado que la aplicación es vulnerable a inyecciones SQL, vamos a aprovechar esta vulnerabilidad para extraer información sensible de la base de datos. Aunque este proceso se puede automatizar con herramientas como SQLMAP, para este ejemplo, lo haremos manualmente.

Primero, necesitamos identificar qué condiciones son VERDADERAS y cuáles son FALSAS para la aplicación. A través de un enfoque de prueba y error, hemos descubierto que los `pageIDs` 1, 2 y 3 son válidos, mientras que el 4 no lo es. Esto nos proporciona una base para continuar con la explotación de la vulnerabilidad.

Ahora, necesitamos inyectar una condición IF en nuestra consulta SQL que nos permita identificar si ciertos casos son VERDADEROS o FALSOS. La idea es hacer que la condición devuelva un valor de 1 para los casos en los que la condición sea VERDADERA y un valor de 4 para aquellos en los que sea FALSA. Esto nos ayudará a obtener una respuesta clara sobre la validez de las condiciones que estamos probando.

El siguiente paso es añadir más lógica a nuestra inyección y empezar a extraer información de las tablas de datos. Ten en cuenta que no veremos directamente los datos recuperados de la base de datos en la página, sino que verificaremos lógicamente si los datos existen.

Para ello, vamos a confirmar si la tabla «users» está presente en la base de datos. Este proceso consiste en realizar pruebas que nos permitan determinar la existencia de la tabla mediante la respuesta de la aplicación.

Dado que no se presentó ningún error, esto indica que la tabla *users* efectivamente existe en la base de datos.

Si probamos con otros nombres de tablas y recibimos un error 404, esto nos confirmará que esas tablas no están presentes. Este método de prueba nos ayuda a identificar las tablas que están disponibles para nuestras consultas.

Vamos a intentar extraer un usuario válido. En vez de utilizar un diccionario con posibles nombres de usuarios para adivinar, podemos verificar si la primera letra del primer usuario es la letra _a_. Esto nos permitirá comprobar la existencia de usuarios basándonos en la letra inicial sin tener que adivinar entre múltiples opciones.

El error muestra que la primera letra del usuario no es una _a_. Intentemos con la letra _A_ en su lugar. Recuerda que las mayúsculas y minúsculas son importantes en este contexto. Al probar con _A_, estamos verificando una posible variación que puede ser correcta.

http://localhost:5000/home/(select case when substr(UserName,1,1)=’A’ then 1 else 4 end from users limit 0,1)    

Como primera suposición, es posible que _Admin_ sea un nombre de usuario válido en la base de datos. Dado que hemos verificado la existencia de la tabla y realizado pruebas iniciales, es un buen momento para poner a prueba esta hipótesis. Intentaremos buscar información relacionada con el usuario _Admin_ para confirmar si efectivamente existe en la base de datos. Este proceso nos permitirá avanzar en la explotación de la vulnerabilidad y extraer datos más específicos.

    Gracias por llegar hasta esta última parte. Espero que la información te haya sido útil. Si tienes alguna duda, no dudes en consultarme. Si te ha gustado el contenido, puedes dejar un comentario para que pueda explorar nuevas series sobre distintas vulnerabilidades o profundizar en los temas tratados. ¡Agradezco tu interés y participación!


Deja una respuesta

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