/sql-injection

Docker Compose para desplegar la aplicación web DVWA (Damn Vulnerable Web Application) para realizar prácticas de SQL Injection.

Primary LanguagePHP

sql-injection

Introducción

Este repositorio contiene un archivo docker-compose.yml para desplegar la aplicación Damn Vulnerable Web Application (DVWA).

DVWA es una aplicación web desarrollada en PHP y MySQL que ha sido diseñada con algunas de las vulnerabilidad más comunes que pueden aparecer en las aplicaciones web.

Puede encontrar más información en el repositorio oficial del proyecto DVWA.

Cómo desplegar la aplicación

Para desplegar la aplicación ejecute el comando:

docker compose up -d

Para detener los contenedores:

docker compose down

Para detener los contenedores y eliminar el volumen de la base de datos:

docker compose down -v

Credenciales por defecto

Las credenciales por defecto para acceder a la aplicación son:

  • username: admin
  • password: password

Creación de la base de datos

La primera vez que acceda a la aplicación tendrá que crear la base datos siguiendo estos pasos:

  1. Seleccione en el menú principal que aparece a la izquierda la opción Setup / Reset DB.

  1. Una vez que esté en la página de configuración de la base de datos, pulse sobre el botón Create / Reset Database que aparece al final de la página.

Estos pasos puede realizarlos siempre que quiera eliminar la base de datos actual y volver a crearla con los datos por defecto.

Configuración del nivel de seguridad

La aplicación permite configurar el nivel de seguridad desde el apartado DVWA Security del menú principal.

Existen cuatro niveles de seguridad: Low, Medium, High y Impossible.

Los ejemplos que se muestran a continuación son para el nivel de seguridad Low.

SQL Injection

De todos los tipos de vulnerabilidades que existen en la aplicación vamos a centrarnos en las de tipo SQL Injection.

Ejemplo 1. Hacer login sin conocer el password

En este ejemplo vamos a seleccionar la opción Brute Force del menú principal, donde nos aparecerá un formulario con dos campos: username y password.

Al final de la página nos aparece un botón con el texto View Source que nos permite ver el código fuente de la página.

En este repositorio se ha incluido el código fuente que utiliza el formulario del ejemplo, para que pueda estudiarlo con detalle. Ver el código fuente del archivo brute_source_low.php.

El código fuente que utiliza esta aplicación para recibir los parámetros del formulario y construir la consulta SQL es el siguiente:

// Get username
$user = $_GET[ 'username' ];

// Get password
$pass = $_GET[ 'password' ];
$pass = md5( $pass );

$query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";

Podemos hacer un ataque de tipo SQL Injection introduciendo el siguiente valor en el campo username del formulario:

admin' #

Al enviar este valor la cadena con la consulta SQL que se ejecutará en la base de datos será la siguiente:

SELECT * FROM `users` WHERE user = 'admin' #' AND password = ...

Tenga en cuenta que todo lo que aparezca después del carácter # será considerado como un comentario y no se ejecutará.

También puede comentar el resto de la consulta utilizando dos guiones seguidos de un espacio, por lo tanto, si enviamos el siguiente valor en el campo username del formulario también podríamos hacer un ataque de tipo SQL Injection:

admin' -- 

Al enviar este valor la cadena con la consulta SQL que se ejecutará en la base de datos será la siguiente:

SELECT * FROM `users` WHERE user = 'admin' -- ' AND password = ...

Ejemplo 2. Obtener el listado de todos los usuarios

En este ejemplo vamos a seleccionar la opción SQL Injection del menú principal, donde nos aparecerá un formulario con un campo para introducir el identificador de un usuario y buscarlo en la base de datos.

Al final de la página nos aparece un botón con el texto View Source que nos permite ver el código fuente de la página.

En este repositorio se ha incluido el código fuente que utiliza el formulario del ejemplo, para que pueda estudiarlo con detalle. Ver el código fuente del archivo brute_source_low.php.

El código fuente que utiliza esta aplicación para recibir el parámetro del formulario y construir la consulta SQL es el siguiente:

// Get input
$id = $_REQUEST[ 'id' ];
...
$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

Podemos hacer un ataque de tipo SQL Injection para obtener el listado de todos los usuarios que existen en la base de datos, introduciendo el siguiente valor en el campo id del formulario:

1' OR 1 = 1 #

Al enviar este valor la cadena con la consulta SQL que se ejecutará en la base de datos será la siguiente:

SELECT first_name, last_name FROM users WHERE user_id = '1' OR 1 = 1 #';

Tenga en cuenta que todo lo que aparezca después del carácter # será considerado como un comentario y no se ejecutará.

Ejemplo 3. Obtener el listado de todas las tablas de la base de datos

En este ejemplo vamos a continuar con el formulario que aparece en la opción SQL Injection del menú principal, donde nos aparece un campo para introducir el identificador de un usuario y buscarlo en la base de datos.

En este caso vamos a utilizar el opedor UNION para ejecutar una nueva consulta donde vamos a solicitar el listado de todas las tablas de la base de datos de la aplicación.

En MySQL existe una base de datos llamada information_schema que contiene información de todas las bases de datos que existen en el sistema gestor de bases de datos. Dentro de esta base de datos existe una tabla llamada tables que almacena información sobre todas las tablas que existen en las bases de datos del servidor.

Puede consultar esta información ejecutando la siguiente consulta SQL desde una consola de MySQL o desde la aplicación web phpMyAdmin que se incluye en el despliegue de este proyecto.

SELECT * FROM information_schema.tables;

Como la consulta que se ejecta en el código la aplicación devuelve dos columnas, la nueva consulta que vamos a inyectar después del operador UNION también tiene que devolver dos columnas.

Para hacer el ataque de tipo SQL Injection que nos permita obtener el listado de todas las tablas de la base de datos de la aplicación, introduciremos el siguiente valor en el campo id del formulario:

' UNION SELECT table_name,NULL FROM information_schema.tables #

Ejemplo 4. Obtener las columnas de la tabla users

Una vez que hemos obtenido el listado de todas las tablas de la base de datos de la aplicación, veremos que existe una tabla llamada users.

Ahora vamos a realizar un ataque de tipo SQL Injection para obtener las columnas de la tabla users.

El valor que tendremos que introducir en el campo id del formulario es el siguiente:

' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name= 'users' #

Ejemplo 5. Obtener el listado de todos los usuarios y sus contraseñas

Una vez que hemos consultado cuáles son las columnas de la tabla users, observamos que exsiten dos columnas con los nombres de user y password.

Vamos a realizar un ataque para obtener el listado de todos los usuarios y sus contraseñas.

En este caso, el valor que tendremos que introducir en el campo id del formulario es el siguiente:

' UNION SELECT user, password FROM users #

Blind SQL Injection

El ataque de tipo Blind SQL Injection es una técnica que se utiliza cuando una aplicación es vulnerable a ataques de tipo SQL Injection pero está configurada para no mostrar los resultados de las consultas que se le están inyectando.

En este caso, el atacante envía consultas SQL a la base de datos de la aplicación vulnerable y analiza las respuestas para determinar si la consulta es verdadera o falsa. Aunque el proceso para obtener información es lento, esta técnica permite a un atacante extraer información de forma indirecta.

Ejemplo 1

En este ejemplo vamos a seleccionar la opción SQL Injection (Blind) del menú principal, donde nos aparecerá un formulario con un campo para introducir el identificador de un usuario y buscarlo en la base de datos.

Para comprobar si la aplicación es vulnerable a un ataque de tipo Blind SQL Injection vamos a introducir el siguiente valor en el campo id del formulario:

1' OR 1 = 1 #

En este caso, la aplicación no nos devuelve el listado de todos los usuarios que existen en la tabla users, pero nos devuelve un mensaje de éxito informándonos que el usuario con el identificador 1 existe en la base de datos. Esto quiere decir que esta aplicación es vulnerable a un ataque de tipo Blind SQL Injection.

Referencias