VulnHub - From SQL Injection to Shell I - CTF Walkthrough

 

Descripción
Este ejercicio explica cómo puede, desde una inyección SQL, obtener acceso a la consola de administración. Luego, en la consola de administración, cómo puede ejecutar comandos en el sistema.
Como primer paso identificaremos la maquina objetivo. Para esto utilizare la herramienta Netdiscover.
netdiscover
Nuestra máquina objetivo tiene la dirección IP 192.168.50.72. Ahora con la herramienta Nmap enumeraré los puertos y servicios que se están ejecutando en la máquina objetivo.
nmap -n -p- -sS --open -min-rate 5000 192.168.50.72
nmap -n -p 22,80 -sV -min-rate 5000 192.168.50.72
Como se observar en las imágenes anteriores se están ejecutando dos servicios. El primero es el servicio SSH mientras que el segundo es Apache como servidor web.

Ahora ejecutaré nuevamente la herramienta Nmap para ejecutar un conjunto de script de Nmap para identificar vulnerabilidades.
map -n -p 22,80 -sC -min-rate 5000 192.168.50.72
Al parecer Nmap no encontró alguna vulnerabilidad. Entonces, lo que haré será visitar la página web que se está ejecutando en el servidor web.
PhotoBlog
Como se muestra en la imagen anterior en la parte superior de la página web marcado con una línea roja es un menú de navegación analizaré cada link.
Photoblog-menú análisis
Como se muestra en la imagen los links |test|ruxcon|2010| se corresponde a la siguiente URL: http://192.168.50.72/cat.php?id=1 (id=1:test, id=2:ruxcon, id=3:2010), donde cat.php?id=1 puede ser un parámetro inyectable, también hay panel de autenticación en el link |admin|.
Photoblog-admin
Debemos analizar también si el formulario web es vulnerable a inyección SQL. Ahora comenzaré analizando el parámetro cat.php?id=1. Existen muchas formas de indentificar si un parámetro es inyectable y comenzaré igualando id=1 a id=' (apóstrofo).
Photoblog parametro inyectable
El parámetro cat.php?id=', es inyectable como se muestra en la imagen anterior se muestra un error de base de datos. Con la prueba anterior sabemos que la base de datos que se está utilizando es MySQL, por lo tanto, las siguientes pruebas tienen que estar dirigidas para esta base de datos en particular.
Valores proveniente de base de datos
Ahora debemos averiguar que valores de la base de datos son mostrados en la página web, para esto debemos primero averiguar cuantas colunas de la base de datos son consultadas por la página web. Para averiguar esto utilizaremos la siguiente carga útil (payload), la instruccion "order by [número de columna]".

Para realizar este tipo de prueba utilizaré un script de Python3 como se muestra en la siguiente imagen.
Payload order by
Al ejecutar el script nos muestra la siguiente información.
Script sql-order-by.py
Como se muestra en la imagen anterior la consulta sql que se ejecuta por la página web contiene 4 columnas. Ahora debemos averiguar cuál de estas columnas son mostrada en la página web.  Para averiguar que columnas son mostrada en la página web utilizaremos la siguiente carga útil (payload), la instrucción "union select null,null,null,null".

Nota: La instruccion union de SQL permite unir dos o más select concatenando los resultados de la ejecución en un único conjunto de resultados. La instrucción union está supeditado por reglas estrictas.
  • Los select que participan en la union tienen que constar con el mismo número de columnas.
  • Las columnas que participan en la union deben ser del mismo tipo de datos o datos compatibles. Por ejemplo. datos de tipo FLOAT o INT.
Con lo anterior, utilizamos el payload "union select null,null,null,null". Sabemos que la consulta cuenta con 4 columnas, por lo tanto, debemos utilizar la instrucción union con 4 columnas para que está no de un error, luego utilizamos los valores null para cada columna, esto debido a que el valor null es compatible con todos los tipos de datos.
union select payload
Como se muestra en la imagen anterior al ejecutar el payload "union select null,null,null,null -- -" se muestra al final de la última imagen un nuevo dato (marcado con una línea roja) "Picture" sin descripción e imagen.

Ahora debemos remplazar cada null del payload por un valor de tipo strings para saber en qué columna de la instrucción union podemos insertar otros tipos de carga útil para obtener información de la base de datos.
Como se muestra en la imagen anterior el segundo null de la instrucción union corresponde a un valor de tipo strings por lo tanto, podemos inyectar otros tipo de payload en esta columna para obtener datos de la base de datos.

Antes de continuar realizando otros tipos de inyección sql, debemos de explicar que es la base de datos information_schema. Es una base de datos no modificable que almacena información sobre otras bases de datos y otros objetos almacenados en un servidor MySQL. Esta información incluye nombres de bases de datos o tablas, tipos de columnas, privilegios de acceso, vistas, restricciones, etc. Por lo tanto, ahora todas nuestras cargas útiles (payload) apuntan a esta base de datos para obtener información de la misma.

Inyectaré la siguiente carga útil, para listar todas las bases de datos que se encuentran en el servidor MySQL.  
select group_concat(schema_name) from information_schema.schemata
de la siguiente manera.
schema_name - payload
http://192.168.50.72/cat.php?id=1%20union%20select%20null,group_concat(schema_name),null,null%20from%20information_schema.schemata%20--%20-

Como se muestra en la imagen anterior el servidor MySQL tiene dos bases de datos information_schema y Photoblog. Donde Photoblog es la base de datos correspondiente a la página web.

Entonces lo que haré será listar las tablas de la base de datos Photoblog, inyectando la siguiente carga útil.
select table_name from information_schema.tables where table_schema = Photoblog
de la siguiente manera.
table_name - payload
http://192.168.50.72/cat.php?id=1%20union%20select%20null,group_concat(table_name),null,null%20from%20information_schema.tables%20where%20table_schema=%22photoblog%22%20--%20-
Al ejecutar el payload anterior se nos muestra las tablas de la base de datos photoblog: categories,pictures,users. Aquí la tabla que nos interesa es la tabla users. La razón es porque en ella se podrían estar almacenando usuario y contraseñas de la aplicación. Cabe recordar que la página web tiene un panel de autenticación.

Para obtener las columnas en la tabla users, inyectaré la siguiente carga útil. 
select columns_name from information_schema.columns where table_schema=photoblog and table_name = users
columns_name - payload
http://192.168.50.72/cat.php?id=1%20union%20select%20null,group_concat(column_name),null,null%20from%20information_schema.columns%20where%20table_schema=%22photoblog%22%20and%20table_name=%22users%22%20--%20-
Como se muestra en la imagen anterior obtuvimos las columnas de la tabla "users" de la base de datos "photoblog".

Ahora nos faltaría obtener los datos de las columnas login y password de la tabla users. Para obtener los datos de esas columnas inyectare la siguiente carga útil.
select login,password from users
user table users
http://192.168.50.72/cat.php?id=1%20union%20select%20null,group_concat(login,%22:%22,password),null,null%20from%20users%20--%20-
Como se muestra en la imagen anterior obtuvimos el nombre de usuario y contraseña para el usuario admin (admin:8efe310f9ab3efeae8d410a8e0166eb2).

La contraseña se almaceno hasheada, por lo tanto, debemos descifrar esa contraseña. Para obtener la contraseña en texto claro utilizare la herramienta online crackstation.
crackstation
La contraseña en texto claro para el usuario admin es P4ssw0rd. Ahora utilizaré esta contraseña para autenticarme en el panel de login de la página web.
admin login
admin - panel
Al autenticarnos se muestra la siguiente pantalla, en ella podemos subir imágenes haciendo clic en el link "add a new picture".
upload-picture
Intentaré de subir un archivo con extensión .php que me permita obtener una conexión reversa, es decir, desde el servidor web a mi máquina atacante (Kali Linux). En la ruta /usr/share/webshells podemos encontrar varios directorios con webshell lista para configurar y utilizar.
webshell
Para este caso utilizaremos el directorio php y la webshell "php-reverse-shell.php".
php-reverse-shell
Ahora debemos realizar algunas modificaciones al archivo "php-reverse-shell.php". lo pimero que haré será cambiar el nombre del archivo a "octopus.php" con la finalidad de que el nombre no se tan evidente.
octopus.php
Las líneas que debemos modificar son 49 y 50 $ip = la dirección IP de nuestra máquina atacante y $port = al puerto de configuraremos a la escucha de la comunicación desde el servidor web a nuestra máquina atacante.

Con lo anterior solo resta subir el archivo al servidor.



  
upload-webshell-failed
Al parecer hay un filtro que no permite subir archivos con extensión .php. Por lo tanto, cambiaré la extensión a .pHp.
webshell-modified
webshell-modified
upñoad-webshell-successful
Cambiando la extensión a mayúsculas y minúsculas se pudo evadir el filtro aplicado por la página web.

Ahora en nuestra máquina atacante debemos ejecutar la herramienta Netcat y dejar a la escucha el puerto 1234.
ahora desde la página web "admin" hacemos clic en el archivo que acabamos de subir al servidor web y si todo va bien, obtendremos una conexión reversa desde el servidor web a nuestra máquina atacante.
optopus
Al hacer clic en el archivo que subimos al servidor se nos muestra la siguiente página web.
web-clic
Y en nuestra máquina atacante obtenemos la conexión desde el servidor web.

reverse-shell-obtained-command
Como se muestra en la imagen anterior obtuvimos una reverse-shell funcional. a partir de una inyección SQL.

Happy Hack!!! 

Comentarios