d4redevil
  • whoami
  • Active Directory
    • Enumeración
    • PowerShell para gestionar Active Directory
    • PowerView & SharpView
    • Ataques a Kerberos
    • Ataque de contraseñas
    • SMB Relay
    • Token Impersonation
    • Golden Ticket
    • LLMNR Poisoning
    • Mimikatz
    • Grupos privilegiados
    • LAPS
  • Linux
    • Enumeración
    • Escalación de privilegios
    • Transferencia de Archivos
  • Windows
    • Enumeración
    • Escalación de privilegios
      • SeImporsonate
      • SeDebugPrivilege
      • SeTakeOwnershipPrivilege
      • Backup Operators
      • DnsAdmins
    • Transferencia de Archivos
  • Scripting
    • Powershell
      • Introducción
      • Cmdlet
      • Alias
      • Comentarios
      • Comandos utiles
      • Variables
      • Tuberías (Pipes)
      • Operaciones
      • Estructuras Condicionales
  • OWASP TOP 10 y Vulnerabilidades Web
    • Inyecciones SQL
      • ¿Qué son las Inyecciones SQL?
      • Laboratorio
      • Inyecciones SQL basada en Uniones
      • Inyecciones SQL basadas en booleanos
      • Inyecciones SQL basadas en tiempo
  • Writeups
    • Hack The Box
      • Linux
        • 🟢Easy
        • 🟡Medium
          • Zipping
        • 🔴Hard
        • ⚫Insane
      • Windows
        • 🟢Easy
          • Devel
          • Grandpa
          • Granny
          • Jerry
          • Optimum
          • Legacy
          • Active
          • Sauna
        • 🟡Medium
        • 🔴Hard
        • ⚫Insane
    • The Hackers Labs
      • Linux
        • 🟢Principiante
          • Papaya
          • Can You Hack Me?
        • 🟡Avanzado
          • Runners
          • El Candidato
          • El Cliente
        • 🔴Profesional
        • ⚫Experto
          • ⚫Thlcppt_v16
      • Windows
        • 🟢Principiante
          • Cocido Andaluz
          • Ensalá Papas
        • 🟡Avanzado
        • 🔴Profesional
          • BlackGold
        • ⚫Experto
    • Dockerlabs
      • 🔵Muy fácil
      • 🟡Fácil
      • 🟠Medio
        • Database
      • 🔴Difícil
    • VulnHub
      • Linux
        • 🟢Easy
        • 🟡Medium
        • 🔴Hard
      • Windows
        • 🟢Easy
        • 🟡Medium
        • 🔴Hard
    • HackMyVM
      • Linux
        • 🟢Easy
        • 🟡Medium
        • 🔴Hard
        • ⚫Insane
      • Windows
        • 🟢Easy
        • 🟡Medium
        • 🔴Hard
        • ⚫Insane
  • Servicios Comunes
    • TCP
    • UDP
    • FTP (21)
    • SMB (445)
    • MySQL (3306)
    • MSSQL (1433)
  • Cheatsheet
    • Reconocimiento
    • Enumeración
    • Enumeración Web
    • Enumeración de CMS
    • Fuerza Bruta
    • Pivoting
    • Msfvenom
    • Utilidades
    • Fuerza bruta
    • Transferencia de Archivos
  • Contenedores
    • Docker
Con tecnología de GitBook
En esta página
  • Obtener las bases de datos
  • Obtener las tablas
  • Obtener las columnas
  • Obtener los datos
  • Conclusiones finales
  1. OWASP TOP 10 y Vulnerabilidades Web
  2. Inyecciones SQL

Inyecciones SQL basada en Uniones

AnteriorLaboratorioSiguienteInyecciones SQL basadas en booleanos

Última actualización hace 5 meses

¡Hola Hacker! Bienvenid@ a un nuevo artículo.

El primero tipo de inyecciones SQL que veremos en esta serie de artículos, son las llamadas inyecciones basadas en uniones.

Un ataque de inyecciones sql basadas en uniones es un tipo de vulnerabilidad en la que un atacante explota una debilidad en una aplicación para inyectar una consulta SQL maliciosa que utiliza la cláusula UNION. El objetivo de este ataque es combinar los resultados de la consulta original de la aplicación con los resultados de una consulta adicional, controlada por el atacante, lo que le permite acceder a información no autorizada.

En otras palabras, este tipo de ataque permite al atacante extraer datos de una base de datos a la que normalmente no tendría acceso, aprovechando la estructura de la base de datos para fusionar los resultados de su propia consulta con los datos que la aplicación originalmente devuelve.

Antes de comenzar, deberemos crear el siguiente script php en la carpeta app, el cual nos ayudara a realizar la demostración.

vim search_user_by_id.php
<?php
// Habilitamos los mensajes de error
ini_set('display_errors', '1');
ini_set('error_reporting', E_ALL); 

$server = "127.0.0.1";
$username = getenv('MYSQL_USER');
$password = getenv('MYSQL_PASSWORD');
$database = getenv('MYSQL_DATABASE');

$conn = new mysqli($server, $username, $password, $database);

if ($conn->connect_error) die('Error al conectarse a la base de datos: ' . $conn->connect_error);

$id = $_GET['id'] ?? '';
$query = "SELECT name FROM users WHERE id=$id";
$res = mysqli_query($conn, $query);

if (mysqli_num_rows($res)) {
	$row = mysqli_fetch_assoc($res);
	echo "Name: " . $row['name'];
} else {
	echo "The user with ID $id does not exist.";
}

mysqli_close($conn);

Una vez creado el script, si ingreamos a nuestra aplicación y le pasamos 1 como valor del parámetro id, vemos que obtenemos el siguiente resultado:

Efectivamente, el usuario con el id 1 es el Admin.

Si le pasamos como valor del id 4, vemos que no que no existe un usuario con este id, lo cual es correcto.

En primer lugar, para comprobar si es estamos frente a un código vulnerable a inyecciones SQL, podemos realizar la siguiente petición:

http://localhost/search_user_by_id.php?id=1'

Agregamos una comilla al final de nuestro parámetro id, también podríamos obviar el valor de nuestro id y enviar simplemente id='.

Vemos que el script nos devuleve un warning el cual indica que la función mysqli_num_rows esperaba recibir un parámetro mysqli_result y recibio un booleano. Lo cual indica que la consulta ha fallado.

if (mysqli_num_rows($res)) {

Linea 18 donde se produce el error.

Al ver que es vulnerable, seguimos explotando la vulnerabilidad para obtener más información, en este caso para conocer la cantidad de campos que se estan listando.

http://localhost/search_user_by_id.php?id=1 order by 1-- - 

Vemos que no devuelve ningun error.

La consulta SQL quedaría de la siguiente forma:

SELECT username FROM users WHERE id=1 ORDER BY 1-- -'

Los "--" (guiones) o "#" se utilizan en MySQL para realizar comentarios, es decir, que todo lo que venga luego de estos no será ejecutado.

La clausula ORDER BY, permite realizar un ordenamiento de los resultados devueltos por la columna. Recibe dos parámetros, el número de columna por el cual aplicar el ordenamiento y el orden ASC (Ascendente por defecto) y DESC (Descendente).

Pero si ingresamos un valor de 2, vemos que devuelve nuevamente un error.

Lo cual es correcto, ya que nuestra consulta devuelve un solo campo (username).

La consulta SQL quedaría de la siguiente forma:

SELECT username FROM users WHERE id=1 ORDER BY 2-- -'

Antes de seguir adelante, expliquemos brevemente en que consiste la clausula UNION SELECT.

La palabra clave UNION en SQL se utiliza para combinar los resultados de varias consultas SELECT. Cuando usas UNION, los resultados de una consulta adicional se agregan al conjunto de resultados de la consulta principal, formando un único conjunto de datos.

Por ejemplo, si tienes la siguiente consulta:

SELECT column_a, column_b FROM table_1 UNION SELECT column_c, column_d FROM table_2

Esto devolverá un único conjunto de resultados con dos columnas: una que contiene los valores de column_a y column_b de table_1, y otra con los valores de column_c y column_d de table_2.

Para que una consulta UNION funcione correctamente, hay dos reglas clave que deben cumplirse:

  1. El número de columnas debe ser el mismo en ambas consultas.

  2. Los tipos de datos de las columnas correspondientes deben ser compatibles entre sí.

En un ataque de inyección SQL utilizando UNION, es importante asegurarse de que estas dos reglas se cumplan. Esto generalmente requiere que el atacante descubra:

  1. Cuántas columnas devuelve la consulta original.

  2. Qué tipo de datos tienen las columnas de la consulta original, para poder inyectar datos que se ajusten a esas columnas.

Ahora que tenemos claro en que consisite la clausula UNION SELECT sigamos con nuestro laboratorio.

Hasta el momento, logramos determinar que el número de columnas devueltas por la consulta es uno y el tipo de dato que tiene la columna es una cadena (string).

Una vez conocemos la cantidad de campos y el tipo de dato, podemos jugar con la clausula UNION SELECT.

Podemos obtener el nombre de la base de datos actualmente en uso usando lo siguiente:

http://localhost/search_user_by_id.php?id=4 union select database()-- - 

Indicamos un valor de id igual a 4 (un id de usuario que no existe) y luego la clausula UNION SELECT indicando como valor a listar el resultado de la función DATABASE() el cual devuelve el nombre de la base de datos actualmente en uso.

La consulta SQL queda de la siguiente manera:

SELECT username FROM users WHERE id=4 UNION SELECT database()-- -'

Obtener las bases de datos

Para poder conocer todas las base de datos existentes, podemos utilizar la base de datos information_schema y la tabla schemata.

  • information_schema Base de datos que almacena información de la esctructura de todas las base de datos

  • schemata Tabla que almacena las base de datos existentes

  • schema_name Campo que almacena el nombre de la base de datos

Usamos el comando LIMIT offset, length para poder listar las base de datos ya que en este caso se muestre un registro unicamente.

http://localhost/searchUsers.php?id=4 union select schema_name from information_schema.schemata limit 0,1-- -

La consulta generada es la siguiente:

SELECT username FROM users WHERE id=4 UNION SELECT schema_name FROM information_schema.schemata LIMIT 0,1-- -'

Otra alternativa es usar la función GROUP_CONCAT

La cláusula GROUP_CONCAT de MySQL se usa para concatenar valores de varias filas en un solo valor, dentro de un grupo definido por la cláusula GROUP BY. Es útil cuando quieres combinar valores relacionados en una sola cadena.

http://localhost/search_user_by_id.php?id=4 union select group_concat(schema_name) from information_schema.schemata-- -
SELECT username FROM users WHERE id=4 UNION SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata-- -'

Obtener las tablas

Listamos las tablas de la base de datos app_db.

http://localhost/searchUsers.php?id=4 union select group_concat(table_name) from information_schema.tables where table_schema='app_db'-- -
SELECT username FROM users WHERE id=4 UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='app_db'-- -'

Vemos que nos devuelve el nombre de la tabla.

Obtener las columnas

Listamos las columnas de la tabla users de la base de datos app_db.

http://localhost/search_user_by_id.php?id=4 union select group_concat(column_name) from information_schema.columns where table_schema='Hack4u' AND table_name='users'-- -
SELECT username FROM users WHERE id=4 UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema='Hack4u' AND table_name='users'-- -'

Obtener los datos

Una vez conocemos el nombre de los campos, podemos obtener los valores:

http://localhost/search_user_by_id.php?id=4 union select group_concat(username) from users-- -

La consulta a ejecutar sería la siguiente:

SELECT username FROM users WHERE id=4 UNION SELECT GROUP_CONCAT(username) FROM users-- -'

0x3A es ":" en hexadecimal

La consulta a ejecutar sería la siguiente:

SELECT username FROM users WHERE id=4 UNION SELECT GROUP_CONCAT(username,0x3A,password) FROM users-- -'

De esta forma, logramos obtener los usuarios.

Conclusiones finales

Las inyecciones SQL basadas en uniones son una amenaza común debido a su efectividad en aplicaciones web mal configuradas. Para prevenir este tipo de ataques, es esencial implementar medidas como el uso de consultas parametrizadas (prepared statements), la validación estricta de las entradas de los usuarios y el principio de privilegios mínimos en las bases de datos. Además, es crucial realizar auditorías y pruebas regulares de seguridad, como pruebas de penetración, para identificar y mitigar posibles vulnerabilidades antes de que sean explotadas. La protección activa y constante es la clave para mantener los sistemas seguros frente a este tipo de ataques.

Espero que estés disfrutando de esta serie de artículos y que la información te sea útil. Si te ha gustado, te animo a compartirla con otros para que más personas puedan beneficiarse.

Si encuentras algún error o tienes sugerencias para mejorar, no dudes en hacérmelo saber. Estoy siempre abierto a tus comentarios.

¡Gracias por leer!

¡Happy Hacking!

Para realizar la prácita de esta inyección utilizaremos nuestro .

Laboratorio