SQL Injection en la universidad
Anuncio:
En esta entrada os vengo a contar una experiencia personal, se trata sobre una vulnerabilidad encontrada en una web de la universidad.
Era un día cualquiera en la oficina, estaba de prácticas y no había mucho por hacer, así que entré en la web de mi escuela y empecé a trastear.
Esta web tiene una sección de noticias, en la cual aparece una lista ordenada de las mismas.
Para verlas, todos los usuarios hacen click en la misma y les aparece un div superpuesto con la descripción de la noticia.
Lo que no todos los usuarios hacen es abrirlas en una pestaña nueva (es mi costumbre), y fue aquí donde descubrí el problema.
Al abrir una noticia en una pestaña nueva, vi que la url de la misma era del tipo:
http://sitio.com/noticias.php?id=23
Aquí se me ocurrió que podríamos probar algo.
Cuando filtramos parámetros para evitar inyecciones SQL, normalmente usamos funciones como mysqli_real_escape: mysqli.real-escape-string
Esta función elimina los caracteres tipo comillas y evita la famosa inyección
http://sitio.com/noticias.php?id=23' or '1'='1
Pero no nos olvidemos del tipo del parámetro, que no es tipo string, sino numérico, y sobre todo, que una consulta no tiene por qué tener comillas.
Así que probé con:
http://sitio.com/noticias.php?id=0 or 1=1
y… bingo! me devolvía la primera noticia de la base de datos.
Ya estaba claro el problema, habían escapado el parámetro ‘id’ como si de un tipo string se tratara, y no como un entero.
El próximo paso era obtener algún tipo de información «importante», por ejemplo, la versión de MySQL o el usuario que corre el proceso en el sistema, para ello, se hacía necesario saber cuántos parámetros tenía la consulta. ¿Por qué? La consulta devolvía una serie de parámetros, título de la noticia, descripción, url del thumbnail, etc, por lo que, para poder ver, por ejemplo, la versión de MySQL en lugar del título de la noticia, se hace necesario saber el número de columnas para hacer un ‘UNION’, veámoslo a continuación.
Fui probando a mano el número de parámetros:
http://sitio.com/noticias.php?id=0 UNION SELECT 1,2,3 --
Así hasta que llegué a 8 parámetros:
http://sitio.com/noticias.php?id=23 UNION SELECT 1,2,3,4,5,6,7,8 --
Con esta consulta me mostraba un ‘2’ donde el título y un ‘4’ donde la descripción de la noticia, por lo que ya sabía que el parámetro 2 era el título y el 4 la descripción, ahora solo tenía que cambiar estos números por alguna función interesante:
http://sitio.com/noticias.php?id=23 UNION SELECT 1,user(),3,version(),5,6,7,8 --
Y listo, ya tenía algo más de información.
En este punto de la historia ya reporté la vulnerabilidad a los encargados de la web en la universidad, pero por motivos de horario no pude citarme con ellos hasta unos días más tarde.
Así que en los siguientes días seguí «sacando petróleo», y vaya que saqué, si hubiera sido oro negro me hubiera forrado de billetes, literalmente.
Aquí es donde entra la herramienta SQLMAP, una herramienta escrita en Python para realizar inyecciones SQL automáticas.
Obtener información con consultas manuales iba a ser trabajo arduo, así que puse a trabajar a la herramienta:
python sqlmap -u http://sitio.com/noticias.php?id=23 --dbs
Y el listado de todas las bases de datos apareció ante mis ojos, después:
python sqlmap -u http://sitio.com/noticias.php?id=23 --tables
Toooodas las tablas… Bingo, había llegado al fondo del asunto… o eso creia 🙂
Decidí descargar a mi equipo los datos para mostrarlos una vez llegada la reunión con los administradores.
python sqlmap -u http://sitio.com/noticias.php?id=23 --dump
Unos 5 minutos más tarde tenía una serie de archivos .csv, uno por cada tabla.
Había información sobre trabajos, prácticas… etc, pero me llamó la atención un fichero llamado ‘profesor-contrasena.csv’, en el cual había distintas tuplas con identificadores de profesores y hashes de sus contraseñas.
En este punto se me ocurrió hacer un script en Python que leyera esos hashes y los buscase en Google, ya que podemos usar a los buscadores como calculadoras de hashes.
Finalmente no obtuve resultado con esto, aunque hubiera estado gracioso obtener el password de algún profesor y haber trasteado más, pero bueno.
Días más tarde hablé con los adminsitradores y les expuse la situación, simplemente tenían que usar la función ‘is_numeric’ para filtrar el parámetro:
función is_numeric de php
Con esta función podemos saber si una variable es numérica o no, por lo que solucionaríamos el problema.
A dia de hoy ya está corregida y los datos eliminados de mi máquina.
Espero que os haya gustado.
HackSaludos!