UNIDAD 2 Tarea 2: SQL Injection

Dentro del MOOC Hacking Ético impartido por Mondragon Unibertsitatea nos serán dictadas varias tareas que deberemos de publicar en nuestro blog personal, dichas tareas las iré colocando en la categoría MOOC Hacking Ético. (Para ver todas las categorías de mi blog haz clic sobre el engrane que está dentro del hexágono café en la parte superior de la página).

*

SQL Injection

Inyección SQL (en inglés SQL Injection) es un método de infiltración de código arbitrario que se vale de errores de programación presentes en una aplicación en el nivel de validación de las entradas para realizar operaciones sobre una base de datos.

El origen de la vulnerabilidad radica en el mal tratamiento que la aplicación da a los datos introducidos por el usuario y que después forman parte de una consulta a la base de datos. Por lo tanto, es completa responsabilidad del programador aplicar las técnicas de filtrado necesarias a los datos enviados por el usuario para prevenir este tipo de ataques.

Ejemplo de SQL Injection

Para entender como funciona la inyección es recomendable tener conocimientos básicos del Lenguaje de Consultas Estructurado (SQL). En este ejemplo la aplicación vulnerable será una aplicación web escrita en PHP.

Imaginemos que nuestra aplicación web vulnerable muestra un formulario con un campo para que el usuario escriba su CURP (Clave Única del Registro de Población) para acceder a un contenido cualquiera. La aplicación haría algo como esto :

$txCURP = $_REQUEST['txCURP'];
$res = mysql_query("SELECT `curp`,`rfc` FROM `t001_001` WHERE `idCURP` = '".$txCURP."'");

Supongamos que el usuario escribe una CURP válida, por ejemplo HEXXXX000000XXXX, la consulta que se construye sería:

SELECT `curp`,`rfc` FROM `t001_001` WHERE `idCURP`='HEXXXX000000XXXX'

Hasta aquí no hay problema, la consulta ejecutada es la que esperaba el programador de la aplicación. Ahora imaginemos que el usuario escribe esto: X’ OR ‘1’=’1. La consulta generada sería:

SELECT `curp`,`rfc` FROM `t001_001` WHERE `idCURP`='X' OR '1'='1'

Vemos como es posible cambiar la lógica de la consulta SQL mediante los datos que envía el usuario. En este caso el resultado de la consulta en vez de contener un registro con la CURP del usuario, contendrá varios registros con todas las CURPs (porque la expresión ‘1’ = ‘1’ siempre es cierta).

Sabiendo inyectar el código correcto un atacante el auditor de seguridad puede obtener todo tipo de información de la base de datos, incluso podría añadir, modificar y eliminar registros, si es que los permisos del usuario MySQL lo permiten. Veamos un par de ejemplos:

Eliminar la tabla t_001001

El auditor de seguridad escribe en el cuadro de texto:

-1'; DROP TABLE t_001001; #

Y la consulta ejecutada es:

SELECT `curp`,`rfc` FROM `t001_001` WHERE `idCURP`='-1'; DROP TABLE t_001001; #'

La almohadilla # convierte el resto de la línea en un comentario, por lo tanto, lo que está después de esta no es ejecutado.

Insertar un registro

Suponiendo que RFC y CURP son los únicos campos de la tabla; el auditor de seguridad escribe en el cuadro de texto:

-1'; INSERT INTO t_001001 VALUES('FAKE-RFC', 'FAKE-CURP'); #'

Y la consulta ejecutada es:

SELECT `curp`,`rfc` FROM `t001_001` WHERE `idCURP`='-1';  INSERT INTO t_001001 VALUES('FAKE-RFC', 'FAKE-CURP'); #'

Obtener información de la base de datos con UNION

Si el atacante auditor de seguridad decide utilizar UNION para unir los resultados de otra consulta a los resultados de la primera, debe de adjuntar el mismo numero de columnas. Es por ello que uno de los primeros pasos sería adivinar cuantas columnas devuelve el primer SELECT.

El siguiente ejemplo provoca un error en la inyección, ya que el número de columnas que devuelve SELECT es mayor al que se intenta unir con UNION. Suponiendo que mysql_query contiene:

$res = mysql_query ("SELECT `idCURP`, `curp`,`rfc`,`apellido1`,`apellido2`, `nombres`, `afore` FROM `tablaX` WHERE `idCURP` = '".$txCURP."'");

El auditor de seguridad escribe en el cuadro de texto:

-1' UNION SELECT 1,2; #

Y la consulta ejecutada es:

SELECT `idCURP`, `curp`,`rfc`,`apellido1`,`apellido2`, `nombres`, `afore` FROM `tablaX` WHERE idCURP='-1' UNION SELECT 1,2; #'

Se aprecia como SELECT devuelve 6 columnas, mientras que solo estamos adjuntando 2 columnas con UNION. Esto genera un error en toda la consulta. Lo que hay que hacer es comenzar a realizar pruebas de inyección (intentando con los siguientes valores en el cuadro de texto):

-1' UNION SELECT 1; #
-1' UNION SELECT 1,2; #
-1' UNION SELECT 1,2,3; #
-1' UNION SELECT 1,2,3,4; #

Y así sucesivamente hasta acertar el número de columnas.

Una vez que se ha conseguido el número de columnas se puede comenzar a utilizar UNION para obtener información importante de la base de datos. Por ejemplo, al introducir en el cuadro de texto:

-1' UNION SELECT 1, 1, 1, version(), user(), database(); #

Obtendremos la versión de MySQL, el usuario actual y la base de datos actual.

Cómo proteger las aplicaciones

Para proteger las aplicaciones de SQL Injection existen varios métodos que varían de acuerdo al lenguaje que estemos usando para programar. En el caso de PHP (si usamos MySQL) la forma más fácil es con la función mysql_real_escape_string(), aunque es obsoleta desde PHP 5.5 y será removida en PHP 7. (En vez de ello se recomienda usar PDO).

Volviendo a la tarea: Tarea 2 Usa la técnica SQL injection para obtener información relevante sobre la estructura de una base de datos.

Para realizar esta actividad, a mí, como alumno inscrito me fue proporcionada una imagen de disco duro de VirtualBox. Dicha imagen contiene un Debian algo modificado y Damn Vulnerable Web App (DVWA) instalado. Si quieres hacer los ejercicios descritos abajo (suponiendo que no estás inscrito en el curso), necesitarás instalar Apache, PHP y MySQL para poder instalar DVWA.

Una vez encendida la máquina virtual nos aparece en la consola de la misma la IP que le fue asignada, esta la usaremos para poder entrar a la interfaz de DVWA.

*

Máquina Virtual con DVWA

Apuntamos la IP y la abrimos un navegador. En mi caso es 192.168.56.101

Nos debe de aparecer la página de inicio de sesión de DVWA, usamos las credenciales correspondientes. Usuario admin, contraseña: password

Del lado izquierdo está el menú, buscamos el apartado “DVWA Security” y le damos clic. Del lado derecho debe de aparecer una lista desplegable con los niveles de seguridad. Seleccionamos “low” y damos clic en el botón “Submit“.

*

Estableciendo niveles de seguridad

Ahora estamos listos para comenzar nuestras pruebas de inyección. Hacemos clic del lado izquierdo en “SQL Injection“. Nos debe de aparecer un formulario con un cuadro de texto, lo que escribamos ahí formará parte de una consulta SQL. Si estás leyendo este artículo desde el principio, esto ya te sonará familiar.

*

Voy a colocar lo que se tiene que escribir en el cuadro de texto y abajo una breve explicación de lo que se realiza.

El funcionamiento “ideal” de la página es que el usuario escriba un número correspondiente al ID de usuario y esta le muestre su ID, primer nombre y apellido.

Inyección básica: Escribimos un 1 en el cuadro de texto y hacemos clic en Submit. La página responde con los datos del usuario 1. La consulta ejecutada es: SELECT first_name, last_name FROM users WHERE user_id = ‘1’. Este es el funcionamiento esperado.

2.2.vbox4

Escenario “siempre cierto”: Escribimos en el cuadro de texto -1′ or ‘1’=’1 y hacemos clic en Submit. La consulta ejecutada es:  SELECT first_name, last_name FROM users WHERE user_id = ‘-1’ or ‘1’=’1′

Quizás no exista un usuario con id -1 así que la primera condición id=’-1′ quizás siempre sea falsa. La segunda condicion ‘1’=’1′ siempre será verdadera. El resultado es que se muestran todos los registros de la tabla.

Mostrando información de la base de datos: Escribimos en el cuadro de texto -1′ UNION SELECT version(), user() UNION SELECT database(), null ; # y hacemos clic en Submit. La consulta ejecutada fue SELECT first_name, last_name FROM users WHERE user_id = ‘-1′ UNION SELECT version(), user() UNION SELECT database(), null ; #’

Aquí vemos que DVWA nos ahorra el trabajo de “adivinar” cuantas columnas devuelve SELECT, pues viene en su documentación. Como sabemos que son 2 columnas procedemos a usar UNION con la misma cantidad de columnas. En el ejemplo quería mostrar 3 datos: versión de MySQL, usuario y base de datos, por lo que necesité usar 2 UNION (cada UNION inserta una fila).

Obtener los nombres de las tablas que tengan el prefijo user: Escribimos en el cuadro de texto -1′ union select null, table_name from information_schema.tables where table_name like ‘user%’; # y hacemos clic en Submit. La consulta que se ejecuta es SELECT first_name, last_name FROM users WHERE user_id = ‘-1’ union select null, table_name from information_schema.tables where table_name like ‘user%’; #’

Pruebas automatizadas de inyección

Como te habrás imaginado hay aplicaciones que nos permiten realizar la inyección SQL de manera automatizada, una de las más populares es Havij. Es una aplicación de paga, pero también hay una versión gratuita limitada.

*

Havij es una herramienta para realizar pruebas de inyección de manera automatizada

Para saber más

Anuncios

3 comentarios en “UNIDAD 2 Tarea 2: SQL Injection

  1. Andrew Vallejo dijo:

    amigo tengo el problema que no arranca la máquina, me podrias ayudar ?
    Fallo al abrir una sesión para la máquina virtual dvwa.

    Interface (‘VirtualBox Host-Only Ethernet Adapter’) is not a Host-Only Adapter interface (VERR_INTERNAL_ERROR).

    Código Resultado: E_FAIL (0x80004005)
    Componente: ConsoleWrap
    Interfaz: IConsole {872da645-4a9b-1727-bee2-5585105b9eed}

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s