Nivel 30-34
Last updated
Last updated
Ingresamos las credenciales para el nivel 30.
Usuario: natas30
Contraseña: WQhx1BvcmP9irs2MP9tRnLsNaDI76YrH
Tras iniciar sesión, nos encontramos con la página de inicio del Nivel 30. Se nos muestra en la página para hacer Login con nuestro usuario y contraseña por lo que revisamos el código fuente.
Este código Perl verifica si el método de solicitud es "POST" y si se proporcionan un nombre de usuario y una contraseña. Si es así, establece una conexión a la base de datos, forma una consulta usando $dbh->quote(param())
, y la ejecuta. Si hay un resultado, se imprime; de lo contrario, se muestra "fail :(".
Aunque la inyección SQL parece una posible vulnerabilidad, intentos comunes como ' OR 1=1 --
no funcionan. Será necesario explorar otras posibles fallos.
Como $dbh->quote(param())
es el encargado de interpretar nuestra entrada y agregarla a la consulta, pensé que debería revisarlo primero. Si existe alguna vulnerabilidad en este punto, sería suficiente para inyectar una cadena maliciosa en la consulta SQL.
Busqué "perl sql injection" y encontré un resultado que apareció entre los primeros. Puedes consultar la discusión completa sobre la vulnerabilidad en conexiones de bases de datos en Perl en la siguiente página de Stack Exchange: Is this Perl database connection vulnerable to SQL injection?
En el código fuente, se espera un nombre de usuario y una contraseña, pero no se restringe a que solo se proporcione un valor para cada uno. Esto significa que podríamos enviar varios valores, lo que convertiría uno de los parámetros en un array.
Además, si quote()
se llama con una lista de valores y el segundo es un entero, quote()
podría devolver un valor sin comillas. Es decir, al proporcionar un array, se podría invocar la segunda definición de quote()
en lugar de la primera, que es la que se esperaba usar.
El código que proporcionamos realiza una solicitud HTTP POST autenticada a un sitio web, pasando datos específicos como parámetros. Usamos una sesión de requests
para gestionar la autenticación básica y enviamos un conjunto de parámetros a la URL especificada. Luego, imprimimos la respuesta del servidor.
Ingresamos las credenciales para el nivel 31.
Usuario: natas31
Contraseña: m7bfjAHpJmSYgQWWeqRE2qVBuMiRNq0y
Tras iniciar sesión, nos encontramos con la página de inicio del Nivel 31. Se nos muestra para subir archivos .csv por lo que revisamos el código fuente.
Inicialmente, pensé en un ataque de inyección CSV, donde se usan valores que comienzan con =
y otros operadores, los cuales se evalúan cuando se abre el archivo. Investigé sobre estos ataques y probé varios payloads, pero no tuve éxito. Esto probablemente se debe a que el archivo CSV no se está abriendo de la manera necesaria (no se evalúa nada, solo se abre como un archivo de texto).
También intenté subir otros tipos de archivos, ya que tenemos capacidades para cargar archivos, pero no obtuve resultados. Del mismo modo, el archivo subido no se procesa como algo ejecutable.
La vulnerabilidad real se encuentra en las llamadas a las funciones $cgi->
.
Encontrar documentación sobre estas funciones antiguas de Perl fue bastante complicado. La vulnerabilidad en cuestión se describe en una charla titulada "Perl Jam 2", presentada por Netanel Rubin en CCC en 2016, entre otras conferencias.
Ahora que hemos cubierto cómo funciona en teoría, probemos en la práctica. Utilicé la edición gratuita de Burp Suite para esto. Si no has usado Burp antes, tengo una publicación en el blog que describe cómo configurarlo.
Con Burp abierto y el tráfico de tu navegador siendo proxyado a través de Burp, visita http://natas31.natas.labs.overthewire.org/ y sube un archivo CSV. El contenido del archivo no es relevante.
En la pestaña Proxy > History, haz clic derecho en la solicitud y selecciona "Send to Repeater".
Necesitarás hacer dos modificaciones. Primero, copia y pega uno de los bloques de form-data
antes de los datos del CSV, utilizando Content-Disposition: form-data; name="file"
seguido de ARGV
. Asegúrate de que los datos del límite (boundary
) coincidan con los de los otros bloques.
Esto sirve para introducir datos adicionales antes del archivo real, de manera que Perl capture el primer descriptor de archivo y su valor como ARGV
.
En segundo lugar, debemos proporcionar un valor para ARGV
(el archivo que queremos abrir). Esto se logra añadiendo ?filename
al final de la URL. Como queremos acceder a /etc/natas_webpass/natas32
, usaremos un ?
seguido de ese valor.
Ingresamos las credenciales para el nivel 32.
Usuario: natas32
Contraseña:NaIWhW2VIrKqrc7aroJVHOZvk3RQMi0B
Tras iniciar sesión, nos encontramos con la página de inicio del Nivel 32. Se nos muestra para subir archivos .csv por lo que revisamos el código fuente. Parecido al nivel anterior.
El código no tiene mucha diferencia relevante del anterior por lo que he creado este script para obtener la contraseña teniendo en cuenta más o menos como la obtuvimos anteriormente.
Este script realiza lo siguiente:
Configura las Credenciales: Utiliza el nombre de usuario y la contraseña para el nivel 32 de Natas.
Envía una Solicitud POST: Envía una solicitud POST al servidor, incluyendo un archivo CSV con un payload y datos adicionales que engañan al servidor para ejecutar un comando.
Extrae la Contraseña: Analiza la respuesta del servidor para encontrar la contraseña del siguiente nivel usando una expresión regular.
Guarda las Credenciales: Simula el almacenamiento de las credenciales del siguiente nivel (nivel 33).
Ingresamos las credenciales para el nivel 33.
Usuario: natas33
Contraseña: 2v9nDlbSF7jvawaCncr5Z9kSzkmBeoCJ
Tras iniciar sesión, nos encontramos con la página de inicio del Nivel 33. Se nos muestra para subir un Firmware.
El código fuente define una clase llamada Executor()
que se activa cuando se carga un archivo:
Verificación del Archivo:
La clase Executor
obtiene el nombre del archivo de la solicitud POST.
Verifica si el tamaño del archivo supera el límite permitido de 4096 bytes.
Moviendo el Archivo:
Mueve el archivo cargado al directorio de subidas utilizando el nombre del archivo, que coincide con el PHPSESSID
.
Verificación al Destruir:
En la función __destruct()
, se asegura de que el directorio actual sea el directorio de subidas.
Problema Principal:
Si el valor resultante de md5_file()
del archivo coincide con el valor de $signature
, el archivo se ejecutará.
Si no coincide, el sistema reportará un fallo y no podremos continuar.
Con esta información, podemos comenzar a idear soluciones para este desafío. Para ello cree este script.
El código PHP proporcionado crea un archivo PHAR (PHP Archive) que contiene objetos PHP serializados. Aquí tienes una breve descripción de lo que hace cada parte:
Clase PHARFile: Define una clase con dos propiedades públicas, $filename
y $signature
. El constructor inicializa estas propiedades.
Creación de una Instancia: Se crea una instancia de PHARFile
con {{0}}
y {{1}}
como marcadores de posición para $filename
y $signature
.
Creación del Archivo PHAR: Se crea un nuevo archivo PHAR llamado test.phar
. La instancia de la clase se serializa y se añade al archivo PHAR como test.txt
.
Salida: El script muestra un mensaje confirmando que se ha creado el archivo PHAR.
Este código está diseñado para explotar la vulnerabilidad de este nivel que permite la carga y ejecución de archivos PHP.
Configuración inicial:
Se definen las credenciales y la URL del objetivo.
Se crea un archivo PHP que leerá la contraseña de la siguiente etapa.
Generación y escritura del archivo PHP:
Se crea un contenido PHP que lee un archivo sensible (en este caso, /etc/natas_webpass/natas34
).
Se calcula el hash MD5 del contenido PHP para verificar la integridad del archivo.
Se lee una plantilla de archivo PHP, se reemplazan los valores de los placeholders con el nombre del archivo y el hash calculado, y se escribe el archivo resultante.
Ejecución del archivo PHP:
Se ejecuta el archivo PHP generado para asegurar que el atributo phar.readonly
no esté activado.
Carga del archivo PHP malicioso:
Se realiza una solicitud POST para cargar el archivo PHP malicioso en el servidor.
Carga del archivo PHAR:
Se crea un archivo PHAR (un archivo comprimido con código PHP) y se sube al servidor. El archivo PHAR está diseñado para ejecutar código PHP arbitrario.
Ingresamos las credenciales para el nivel 34.
Usuario: natas34
Contraseña: j4O7Q7Q5er5XFRCepmyXJaWCSIrslCJY
Tras iniciar sesión, nos encontramos con la página de inicio del Nivel 34. Finalizamos de momento todos los niveles.