Web Hacking: Inyección SQL. Primeros pasos y ejemplo con una web real usando SQLMap

Parece que desde hace un tiempo, tras el robo de cuentas de Adobe y los últimos “hackeos” a webs conocidas como “Ashley Madison” o “Patreon”, alguna gente ha empezado a tener conciencia de que todo lo que se exponga en Internet es vulnerable a ser atacado. Aún así, un alto porcentaje de las webs en Internet son vulnerables a ser atacadas mediante diferentes técnicas.

En el mundo en que vivimos sigue habiendo mucho analfabetismo tecnológico y mucho falso informático que aún teniendo título universitario, no ha oído hablar jamás de temas de seguridad, pentesting, etc…. Estos individuos son los que se acaban dedicando a crear webs a “manporro” sin tener en cuenta factores como la seguridad, exponiendo en muchos casos desde las bases de datos internas, hasta los nombres y contraseñas para administrar el servidor donde se aloja la web vulnerable.

Aunque existen muchísimas técnicas diferentes, uno de los típicos ataques a webs es el conocido como “SQL Injection”, que no es más que la inyección o “incrustación” de comandos SQL en los parámetros de entrada de una petición HTTP (GET, POST) para conseguir cosas como el volcado de toda la base de datos interna de una web, incluyendo las típicas tablas tipo “users”, con los nombres de usuario y contraseñas. O incluso, tablas tipo “credit_cards” o “payments” con información muy sensible.

sqlmap

Como el tema de la inyección SQL es bastante extenso, y es imposible concentrar todo el conocimiento en una sola entrada, hoy me voy a centrar en, mediante un ejemplo de la vida real, enseñaros lo fácil que es encontrar y atacar webs vulnerables a inyecciones SQL. Para el ejemplo en cuestión, voy a utilizar una web que he encontrado mientras hacía este post, a ratos en mis trayectos en tren, pero hay miles de webs tanto o incluso más vulnerables que ésta.

Logicamente voy a ocultar los datos que revelen de que web se trata, ya que esta entrada del blog la escribo con fines meramente educativos. No hace falta que diga que esto no es para ir “jodiendo” a la gente. Se trata de que aprendas algo nuevo y no de ir cometiendo delitos. Si encuentras una web vulnerable, no te la “cargues” o difundas información alguna de ésta. Lo mejor que puedes hacer es simplemente dejarla tal como estaba cuando termines tus tests. Lo suyo sería notificárselo al webmaster que proceda para que asegure la web, pero hay mucho “capullo” suelto que aún se le ocurriría denunciarte. Para evitar problemas, lo mejor, pasar desapercibido.

injection

Aunque la inyección SQL se puede hacer “a pelo”, para el ejemplo vamos a utilizar una fantástica herramienta que automatiza todo el proceso llamada “SQLMap”. Este script escrito en Python, una vez dada una URL, es capaz de testear todos los parámetros en busca de posibles vectores de ataque. La herramienta es muy completa y es capaz de comprobar también ataques tipo “blind” (a ciegas), en donde puede averiguar que motor de base de datos hay detrás de la web simplemente basándose en el tiempo que tarda el servidor en responder.

Como cualquier otro tipo de ataque, éste se debe hacer protegiendo nuestra identidad, es decir, ocultando nuestra IP. Con SQLMap podemos usar la red Tor, proxies y demás, pero para el ejemplo voy a hacer que tenga salida a Internet directa, es decir, me conectaré directamente al servidor presa.

Aunque mucha gente utiliza la distro “Kali Linux”, que lleva incluida todo un arsenal de utilidades para el pentester, es posible instalar esta herramienta en cualquier distro de tu elección. En mi caso, el portátil del trabajo en el que tengo instalado un Ubuntu 14.04

INSTALACIÓN EN UBUNTU

Clonamos el proyecto en nuestro PC con git:

git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev

Copiamos todo lo descargado a /opt:

sudo mv ./sqlmap-dev/ /opt/

Editamos el fichero “~/.bashrc” y añadimos lo siguiente para que esté siempre disponible:

#sqlmap path
export SQLMAP_HOME=/opt/sqlmap-dev
export PATH=$PATH:$SQLMAP_HOME

Y finalmente creamos un “soft link” para no tener que escribir la extensión “.py” todo el rato:

ln -s /opt/sqlmap-dev/sqlmap.py /opt/sqlmap-dev/sqlmap

BUSCANDO PRESAS

Lo primero que vamos a hacer no es utilizar la herramienta, sino hacer una búsqueda en Google en busca de posibles víctimas. Sí, Google te ayuda a encontrar webs vulnerables, aunque si bien es cierto, en los últimos tiempos ha comenzado a filtrar las búsquedas aún más para evitar que lo utilices con estos fines.

Podemos hacer búsquedas simples o más elaboradas, pero como truco os aconsejo poner en la búsqueda de Google lo siguiente:

inurl: .asp?id= <loquequieras>

El parámetro “inurl: .asp?id” es para decirle a Google que busque páginas que contengan “<loquequieras>”, pero que en su URL tengan “.asp?id=”. Podéis buscar también por “.php?id=”, “.jsp?id=”, … si deseáis páginas PHP, JSP, … , pero por experiencia os digo que hay muchas más páginas que utilizan las antiguas “Active Server Pages” de Mocosoft que no filtran los parámetros de entrada, ya que la gente no solía utilizar tantos “frameworks”, como hoy en día hacen con PHP, que se encargan de filtrar los parámetros por tí. Lo de “id=” es porqué es el tipo de parámetro más común que enlazan directamente con el campo “id” de cualquier tabla de una base de datos, es decir, hacen una consulta SQL con ese parámetro sin filtrar y por ende, puede ser vulnerable a inyecciones SQL. En cualquier caso, también podéis utilizar los operadores de Google que mas os gusten. Esto es solo un ejemplo.

Como advertencia os diré que es más que probable que Google te muestre una página con una prueba tipo “Captcha” para asegurarse que eres una persona y no un “bot”, ya que éstas son las típicas consultas que hacen muchos robots en busca de posibles servidores vulnerables. Para muestra la siguiente captura de pantalla.

captcha

En cualquier caso, tanto si buscas objetivos en la Red, como si ya lo tenías decidido con antelación, el siguiente paso es hacer funcionar “SQLMap” para que nos busque posibles vectores de ataque en la URL que le demos.

DETECTAR SI UNA URL ES VULNERABLE O NO

La URL que voy a utilizar para el ejemplo es del tipo “http://www.xxxxxxxxx.es/index.php?id=4”, por lo que para empezar a comprobar si es posible atacar a esta web a través de su parámetro id, procedemos a llamar “sqlmap” de la siguiente forma:

sqlmap -u http://www.xxxxxxxxx.es/index.php?id=4

Una vez ejecutado, el script empezará a comprobar si es posible o no atacar la web a través del parámetro “id”. Al principio me dice que este no parece ser inyectable, pero mas adelante, empieza a probar ataques tipo “blind” y parece que entonces si es atacable. Tras probar varios ataques “blind”, detecta que se trata de la bbdd MySQL y me pregunta:

it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]

Durante la ejecución del script y según sea vuestra presa, el script os irá haciendo distintas preguntas.

En mi caso le respondo “y”, ya que tratándose de una página tipo “php”, y después de averiguar que es MySQL, no hace falta que siga perdiendo el tiempo probando ataques para otro tipo de bbdd.

Acto seguido, otra pregunta:

for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]

A lo que contesto que “n” y el script sigue con ejecución. En caso de no entender muy bien la pregunta, simplemente probáis una u otra opción. Si os equivocáis y queréis repetir los tests, necesitaréis borrar que guarda, bajo “~/.sqlmap/output/”, simplemete con un:

rm -R ~/.sqlmap/output/<dominiodelaURL>

La próxima vez que ejecutéis el script, en vez de recuperar los datos desde la cache, volverá a ejecutarse completamente desde cero. Ojo, solo borrar la cache si queréis empezar de nuevo otra vez, lo cual no es muy aconsejable.

Finalmente me pregunta…

GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]

Al parecer, el parámetro id es vulnerable. Me pregunta si quiero saltarme el “testeo” para otros parámetros si los hubiera. Como solo le he pasado el parámetro “id” no tiene sentido seguir probando otros, así que contesto “y”.

Y para terminar me vuelve a decir que la bbdd es MySQL y termina la ejecución del script.

[08:26:34] [INFO] the back-end DBMS is MySQL

Cabe resaltar que, durante esta primera ejecución, SQLMap podría detectar, en el caso que así fuera, que no puede funcionar debido a que el servidor ofrece algún tipo de protección (firewall, mod_security, etc…) contra ataques automatizados. No es nada raro y debería ser lo deseable que los servidores web, aun teniendo páginas vulnerables, estuvieran protegidos para detectar y abortar distintos tipos de ataques. Incluso, podría darse el caso de que el servidor “baneara” tu IP por considerarte un peligro potencial.

RECUPERANDO LOS NOMBRES DE LAS BASES DE DATOS

Ahora que ya sabemos de que tipo de motor de base de datos se trata, pasemos a averiguar que nombres de bbdd hay disponibles. Paso previo ala obtención de las tablas. Ejecutamos:

sqlmap -u http://www.xxxxxxxxx.es/index.php?id=4 --dbs

y el script volverá de nuevo donde lo dejó en la anterior ejecución, asumiendo que se trataba del motor MySQL, es decir, no volverá a intentar averiguar de que motor se trata, sino que recupera los datos de la cache. Así sera siempre con futuras ejecuciones de SQLMap sobre la misma URL.

El tiempo que tarde el script en recuperar datos a partir de ahora variará dependiendo del tipo de ataque SQL. Es decir, en mi caso, al ser un ataque tipo “blind”, SQLMap necesita recuperar letra por letra en base a los tiempos de espera, por lo que la ejecución es algo lenta. En el caso de ataques SQL normales, donde el servidor “escupe” directamente las consultas SQL, el proceso es muchísimo mas rápido.

Poco a poco el servidor va mostrando los datos y puedo ver como hay dos bbdd disponibles:

dbs

Y si conocéis algo de MySQL (deberíais…), entonces ya sabréis que la bbdd “real” es “db372191952”.

Pasemos ahora a ver que tablas hay dentro de esta base de datos.

RECUPERANDO LOS NOMBRES DE LAS TABLAS

Para recuperar el listado de tablas de una bbdd  en particular ejecutamos:

sqlmap -u http://www.xxxxxxxxx.es/index.php?id=4 --tables -D db372191952

Tras una pequeña demora, el script empezará a mostrar los nombres de las tablas. Si queréis que vaya mas rápido basta con modificar el numero de “threads”. Este número se puede especificar con el modificador “–threads=X” al ejecutar SQLMap y en vez de probar inyección tras inyección, irá “testeando” varias al mismo tiempo. Debo destacar que tengáis cuidado con este número , porqué es el número de peticiones simultáneas al servidor y si, éste tiene algún tipo de protección, es más fácil que salten estos sistemas, nos bloquee las peticiones y no podamos hacer nada.

Finalmente, SQLMap nos muestra el nombre de las tablas de la bbdd db372191952:

tables

 

RECUPERANDO EL CONTENIDO DE LAS TABLAS

Bien, ahora que ya tenemos el listado de todas las tablas de la bbdd, vemos en concreto 2 que llaman mi atención y de las que podemos sacar alguna información sensible. Por un lado la tabla “tpv”, que como su nombre indica, debe de ser algún tipo de tabla relacionada con una pasarela bancaria o terminal de pago, aunque en mis pruebas previas, he podido ver que la tabla esta vacía y no nos sirve para este ejemplo en cuestión (hubiera estado bien encontrar algún tipo de información bancaria sensible ;-)…). Y por otro lado, tenemos una tabla “Users”, de la cual podemos sacar alguna información valiosa.

La web en concreto que utilizo para estas pruebas, tiene un apartado de usuario y contraseña que permite entrar en un modo de administración de la página (CMS). En el caso que consigamos un usuario y contraseña con derechos “admin” de la tabla ‘Users’, podríamos llegar “loguearnos” y tener el control total de esta web. Eso lo veremos un poco mas adelante.

Aunque queremos recuperar el contenido de la tabla ‘Users’, antes necesitamos saber como se llaman las columnas o campos de la tabla ‘Users’. Simplemente con un:

sqlmap -u http://www.xxxxxxxxx.es/index.php?id=4 --columns -D db372191952 -T Users

el script empezará a intentar extraer los nombres de estas columnas. En mi caso particular no ha podido recuperarlos y me ha preguntado si probaba con nombres de columnas comunes. Se lo he confirmado y tras un rato probando, finalmente me las ha mostrado.

columns

Ahora, una vez recuperadas las columnas,  ya podemos pasar a hacer un volcado de la tabla “Users”, aunque si bien es cierto, el paso previo de recuperar los nombres de las columnas es innecesario, ya que en el momento de volcar las tablas, si SQLMap no conociese el nombre de éstas, iniciará, como paso previo, la recuperación de los nombres de éstas.

Para volcar todas las filas de la tabla basta con escribir:

sqlmap -u http://www.xxxxxxxxx.es/index.php?id=4 --dump -D db372191952 -T Users

El script comienza a sacar carácter a carácter cada columna de cada fila, ya que como mencione anteriormente, la web con la que estoy utilizando SQLMap solo puede ser atacada mediante ataques tipo “blind”.

Después de un largo rato, ya ha recuperado todos los datos y el script detecta que las contraseñas de esta tabla son en realidad “hashes” MD5, así que me pregunta si deseo guardar éstos para un análisis posterior. Es curioso que siendo una página tan “cutre”, al menos hayan guardado “hashes” MD5 en vez de contraseñas en texto plano.
Buen intento, aunque lástima por el webmaster, ya que MD5 hoy en día no se considera para nada seguro. En la red podéis encontrar colecciones de “hashes” MD5 precalculados de un número elevado de combinaciones de caracteres aleatorios.

do you want to store hashes to a temporary file for eventual further processing with other tools [y/N]

Una vez guardados los “hashes”, me pregunta si deseo probar intentar sacar las “passwords” reales a partir de un fichero que contenga “hashes” precalculados:

do you want to crack them via a dictionary-based attack? [Y/n/q]

a lo que logicamente le digo que sí y empieza el proceso de sacar contraseñas a partir de los “hashes” MD5

Me pregunta que diccionario usar y en este momento no dispongo de ninguno, así que para el ejemplo, pulsamos un simple “Enter” para que utilice el diccionario que trae por defecto.

what dictionary do you want to use?
[1] default dictionary file '/opt/sqlmap-dev/txt/wordlist.zip' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files

 

cracking

Y tras unos minutos intentando averiguar las contraseñas….. TACHAN!!! ya tenemos varios posibles combinaciones de usuarios y contraseñas para “loguearnos” como “admins”. Incluso SQLMap tiene la deferencia de guardarnos toda esta información en un maravilloso archivo “.csv”. ¿ Se puede pedir más ?

usera

En concreto, la web que utilizo para el ejemplo no tiene un rol “admin” “per se”, sino que mediante las columnas “correo”, “paises” y “noticias” se le dá a cada usuario la posibilidad de modificar o no estas secciones.

Tas loguearme en la página con el usuario “javier diaz” veo que puedo acceder y modificar noticias y demás.

userpass

admin

Como entenderéis, he ofuscado datos sensibles para que ningún lector con ganas de hacer el mal se vaya a esta página y comience a “trolearla”. Como dije al principio, esto SIEMPRE es con fines educativos y jamás se debe ni “crackear” ni difundir datos de las páginas que logréis “hackear”.

¿ESTO ES TODO LO QUE SE PUEDE HACER CON SQL MAP?

No, esto solo es la punta del iceberg. Este post es simplemente una introducción a los pasos más sencillos de SQLMap y por supuesto, se pueden hacer muchísimas cosas más. A bote pronto se me ocurre… leer y escribir ficheros en el servidor o ejecutar comandos arbitrarios dependiendo de la configuración del servidor, con lo cual, aparte del control de la web, también nos podríamos hacer con el control del servidor.

Happy hacking.

Si te ha gustado y quieres compartir esta página..